工厂设计模式

1、属于创建型设计模式,需要生成的对象叫做产品 ,生成对象的地方叫做工厂

2、使用场景

  • 在任何需要生成复杂对象(构造函数有很多参数的地方,都可以使用工厂方法模式
  • 直接用new可以完成的不需要用工厂模式

3、简单(静态)工厂

  • 抽象一个面条基类,(接口也可以),这是产品的抽象类
public class SimpleNoodlesFactory {
    public static final int TYPE_LZ = 1;//兰州拉面
    public static final int TYPE_PM = 2;//泡面
    public static final int TYPE_GK = 3;//干扣面

    public static INoodles createNoodles(int type) {
        switch (type) {
            case TYPE_LZ:
                return new LzNoodles();
            case TYPE_PM:
                return new PaoNoodles();
            case TYPE_GK:
            default:
                return new GankouNoodles();
        }
    }
}
  • 客户端调用
/**
 * 简单工厂模式
 */
 INoodles noodles = SimpleNoodlesFactory.createNoodles(SimpleNoodlesFactory.TYPE_GK);
 noodles.desc();

特点:

  • 具体的类,非接口 抽象类
  • 重要的create()方法,利用if或者 switch创建产品并返回
  • create()方法通常是静态的,所以也称之为静态工厂

缺点:

  • 扩展性差(增加一种面条,除了新增一个面条产品类,还需要修改工厂类方法)
  • 不同的产品需要不同额外参数的时候 不支持

4、简单工厂(反射)

  • Class.forName(clz.getName()).newInstance()实现的简单工厂
public class StaticNoodlesFactory {
    /**
     * 传入Class实例化面条产品类
     *
     * @param clz
     * @param <T>
     * @return
     */
    public static <T extends INoodles> T createNoodles(Class<T> clz) {
        T result = null;
        try {
            result = (T) Class.forName(clz.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}
  • 客户端调用
        //兰州拉面
        INoodles lz = StaticNoodlesFactory.createNoodles(LzNoodles.class);
        lz.desc();

特点:

  • 具体的类,非接口 抽象类
  • create()方法,是利用反射机制生成对象返回
  • 好处是增加一种产品时,不需要修改create()的代码

缺点:

粗看牛逼,细想之下,不谈reflection的效率还有以下问题:

  • Class.forName(clz.getName()).newInstance()调用的是无参构造函数生成对象,它和new Object()是一样的性质
  • 工厂方法应该用于复杂对象的初始化 ,当需要调用有参的构造函数时便无能为力了,这样像为了工厂而工厂
  • 不同的产品需要不同额外参数的时候 不支持

5、多方法工厂(常用)

  • 多方法的工厂模式为不同产品,提供不同的生产方法
  • 使用时 需要哪种产品就调用该种产品的方法,使用方便、容错率高
public class MulWayNoodlesFactory {

    /**
     * 模仿Executors 类
     * 生产泡面
     *
     * @return
     */
    public static INoodles createPm() {
        return new PaoNoodles();
    }
    
    ...
}
  • 客户端调用:
   /**
         * 多方法静态工厂(模仿Executor类)
         */
        System.out.println("==============================模仿Executor类==============================" +
                "\n 这种我比较青睐,增加一个新面条,只要去增加一个static方法即可,也不修改原方法逻辑");
        INoodles lz2 = MulWayNoodlesFactory.createLz();
        lz2.desc();
  • java.util.concurrent.Executors类便是一个生成Executor 的工厂 ,其采用的便是 多方法静态工厂模式
  • 方便创建 同种类型的 复杂参数 对象

6、普通工厂

  • 普通工厂就是把简单工厂中具体的工厂类划分成两层:抽象工厂层+具体的工厂子类层
public abstract class NoodlesFactory {
    public abstract INoodles create();
}
...
public class LzFactory extends NoodlesFactory {
    @Override
    public INoodles create() {
        return new LzNoodles();
    }
}
  • 客户端调用
  /**
         * 普通工厂方法:
         */
        System.out.println("===========================普通工厂方法==============================" +
                "\n 这种要多写一个类,不过更面向对象吧 = = ,实际中我更倾向于使用【模仿Executor类】的方式");
        NoodlesFactory factory1 = new GankouFactory();
        INoodles gk3 = factory1.create();
        gk3.desc();

普通工厂与简单工厂模式的区别:

  • 不仅仅做出来的产品要抽象, 工厂也应该需要抽象
  • 工厂方法使一个产品类的实例化延迟到其具体工厂子类
  • 当需求变化,只需要增删相应的类,不需要修改已有的类
  • 而简单工厂需要修改工厂类的create()方法
  • 多方法静态工厂模式需要增加一个静态方法

缺点:

  • 每次新增一个具体产品类,也要同时新增一个具体工厂类

7、抽象工厂

  • 工厂都是单产品系的,抽象工厂是多产品系
public abstract class AbstractFoodFactory {
    /**
     * 生产面条
     *
     * @return
     */
    public abstract INoodles createNoodles();

    /**
     * 生产饮料
     */
    public abstract IDrinks createDrinks();
}

缺点

  • 将工厂也抽象后,有个显著问题,就是类爆炸
  • 每次拓展新产品种类,需要修改抽象工厂类,因此所有的具体工厂子类,都被牵连,需要同步被修改

转载于:https://my.oschina.net/u/3847203/blog/1830845

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值