前言(八问)
1.1简介
- 简单工厂模式属于创建型模式,简单工厂模式就是由一个工厂对象来决定创建出一种具体的产品
- 在简单工厂模式中,我们会定义一个创建对象的类,多使用反射的方法来创建具体产品实例,这个类用来封装实例化对象的行为
- 在软件开发中,当我们需要大量的创某种,某类或者某一批对象的时候,就可以考虑使用简单工厂模式
- 简单工厂一般分为:普通简单工厂,多方法简单工厂,静态方法简单工厂
1.2 为什么会出现工厂模式
如果使用传统方式生产披萨,那么实现的类图如下:
如果,我们增加披萨的种类,再增加生产披萨的商店,那么类图如下
1.3简单工厂模式
从上面的类图中我们就可以看出这种实现方法违背了设计模式的对扩展开放,对修改关闭 的原则,当我们要增加一个新的披萨种类时,我们需要修改所有的生产披萨商店的代码,从类图中我们就可以看出生产披萨的商店和披萨之间耦合太严重,于是总结出一种约定俗成的实现套路,即工厂模式类图如下:
将创建对象的行为封装到一个类中,当新的种类加入时候只需要修改种类即可,其他创建对象的行为则不需要修改,这就是简单工厂模式.
当我们只需要一个工厂就能满足需求的时候,我们可以简化工厂模式,将创建对象的方法改用静态方法,这就是静态工厂模式
1.4简单工厂模式实例
抽象产品类
/**
* @Description: 披萨的抽象准备方法
* @Auther: zhugefeng
* @Date:2021/8/6 18:36
**/
public interface Pizza {
void prepare();
}
具体产品类
/**
* @Description:
* @Auther: zhugefeng
* @Date:2021/8/6 18:37
**/
public class CheesePizza implements Pizza{
@Override
public void prepare() {
System.out.println("芝士披萨开始准备...");
}
}
简单工厂类
/**
* @Description: 创建具体产品
* @Auther: zhugefeng
* @Date:2021/8/6 18:35
**/
public class SimpleFactory {
public static Pizza createPizza(){
return new CheesePizza();
}
}
客户端调用
/**
* @Description:
* @Auther: zhugefeng
* @Date:2021/8/6 18:41
**/
public class TestPizza {
public static void main(String[] args) {
Pizza cheesPizza = SimpleFactory.createPizza();
cheesPizza.prepare();
}
}
示例
public interface Sender {
void send();
}
public class QQSender implements Sender{
@Override
public void send() {
System.out.println("QQ发送");
}
}
public class WXSender implements Sender{
@Override
public void send() {
System.out.println("微信发送");
}
}
public class ProductFactory {
public static int QQ = 1;
public static int WX = 2;
public static Sender getInstace(int type){
Sender sender = null;
switch (type){
case 1:
sender = new QQSender();
break;
case 2:
sender = new WXSender();
break;
default:
System.out.println("参数不合法");
break;
}
return sender;
}
}
public class TestProductFactory {
public static void main(String[] args) {
Sender qq = ProductFactory.getInstace(ProductFactory.QQ);
qq.send();
Sender wx = ProductFactory.getInstace(ProductFactory.WX);
wx.send();
}
}
1.5工厂方法模式
在简单工厂模式中,我们是将对象的创建实现在工厂类中,如果,存在不同的工厂,每个工厂的实例化对象方法不一样,此时就出现了工厂方法模式,就是工厂定义创建产品的抽象方法,将产品的具体实例化推到子类去子类去实现.
1.6工厂方法模式实例
抽象产品
/**
* @Description: 获取披萨名称,价格
* @Auther: zhugefeng
* @Date:2021/8/6 18:48
**/
public interface IPizza {
String getPizzaName();
Double getPrice();
}
具体产品实现类
public class BjCheesePizza implements IPizza{
@Override
public String getPizzaName() {
return "北京芝士披萨";
}
@Override
public Double getPrice() {
return 9999.99;
}
}
public class ShCheesePizza implements IPizza{
@Override
public String getPizzaName() {
return "上海芝士披萨";
}
@Override
public Double getPrice() {
return 8888.88;
}
}
抽象工厂
/**
* @Description:
* @Auther: zhugefeng
* @Date:2021/8/6 18:55
**/
public interface ICreateFactory {
IPizza getCreatePizza();
}
具体工厂实现
public class BjPizzaFactory implements ICreateFactory{
@Override
public IPizza getCreatePizza() {
return new BjCheesePizza();
}
}
public class ShPizzaFactory implements ICreateFactory{
@Override
public IPizza getCreatePizza() {
return new ShCheesePizza();
}
}
客户端调用
public class TestFactory {
public static void main(String[] args) {
IPizza p1 = new BjPizzaFactory().getCreatePizza();
System.out.println("您选择的披萨是:"+p1.getPizzaName());
System.out.println("价格为"+p1.getPrice());
}
}
1.7抽象工厂模式
抽象工厂模式实际是将简单工厂模式和工厂方法模式进行一个整合,其类图如下:
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据里氏替换原则,任何接受父类型的地方,都应当能够接受子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例。
1.8总结
工厂模式的意义就是将实例化对象的行为提取出来,放在一个类中统一的管理和维护,符合设计原则中的依赖抽象的原则
简单工厂优缺点
优点:
- 简单工厂的特点就是”简单粗暴”,通过一个含参的工厂方法,我们可以实例化任何产品类,上至飞机火箭,下至土豆面条,无所不能.所以简单工厂有一个别名:上帝类.
缺点:
- 任何”东西”的子类都可以被生产,负担太重.当所要生产产品种类非常多时,工厂方法的代码量可能会很庞大
- 在遵循开闭原则(对拓展开放,对修改关闭)的条件下,简单工厂对于增加新的产品,无能为力,因为增加新产品只能铜锅修改工厂方法来实现.
工厂方法模式优缺点
优点:
- 工厂方法模式就很好的减轻了工厂类的负担,把某一类/某一种东西交由一个工厂生产
- 同时增加某一类”东西”并不需要修改工厂类,只需要添加生产这类”东西”的工厂即可.使得工厂符合开闭原则.
缺点:
- 相比简单工厂,实现略复杂.
- 对于某些可以形成产品族的情况处理比较复杂(相对抽象工厂)
抽象工厂模式优缺点
优点:
- 抽象工厂模式隔离了具体类的生产,使得客户并不需要知道什么被创建.
- 当某一个产品族的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族的对象.
- 增加新的具体工厂和产品族很方便,无需修改已有系统,符合”开闭原则”
缺点:
- 增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类