设计模式の工厂模式

简单工厂模式

  • 简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。

  • 简单工厂模式是工厂模式家族中最简单实用的模式

  • 简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)

  • 在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式.

  • 手机制造顶层接口

public interface Phone {
    void make();
}
  • 小米制造商

public class XiaoMiPhone implements Phone {
    @Override
    public void make() {
        System.out.println("制造了一台小米手机");
    }
}
  • 华为制造商

public class HuaWeiPhone implements  Phone{
    @Override
    public void make() {
        System.out.println("制造了一台华为手机");
    }
}
  • 手机制造代工厂(富士康)

public class PhoneFactory {
    public Phone makePhone(String phoneType){
        if ("xiaomi".equals(phoneType)){
            return new XiaoMiPhone();
        }else if ("huawei".equals(phoneType)){
            return new HuaWeiPhone();
        }
        return null;
    }
}
  • 用户需求方

public class TestMain {
    public static void main(String[] args) {
        PhoneFactory phoneFactory = new PhoneFactory();
        Phone xiaomi = phoneFactory.makePhone("xiaomi");
        xiaomi.make();
        Phone huawei = phoneFactory.makePhone("huawei");
        huawei.make();
    }
}
  • 类图如下所示

简单工厂模式的缺点就在于

通过上面制造手机的列子可以看出,此时我们的工厂只能生产华为和小米两款手机

  • 如果想要生辰更多的品牌手机,那就的在工厂中加条件适配

  • 没增加一个手机品牌,就要去修改工厂的源码,这种操作不符合开闭原则

  • 但是我们可以对其进行优化,使其符合开闭原则

//    public Phone makePhone(String phoneType){
//        if ("xiaomi".equals(phoneType)){
//            return new XiaoMiPhone();
//        }else if ("huawei".equals(phoneType)){
//            return new HuaWeiPhone();
//        }
//        return null;
//    }
public Phone makePhoneOptimize(Class <? extends Phone> clazz){
        if (null != clazz){
            try {
                return clazz.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

然后使用者对应的使用方式也跟着改变一下

//        PhoneFactory phoneFactory = new PhoneFactory();
//        Phone xiaomi = phoneFactory.makePhone("xiaomi");
//        xiaomi.make();
//        Phone huawei = phoneFactory.makePhone("huawei");
//        huawei.make();
​
        PhoneFactory phoneFactory = new PhoneFactory();
        Phone xiaomi = phoneFactory.makePhoneOptimize(XiaoMiPhone.class);
        xiaomi.make();
        Phone huawei = phoneFactory.makePhoneOptimize(HuaWeiPhone.class);
        huawei.make();
​
    }

这样,即使我们继续扩展更多的品牌生产线,也可以不用动这一部分的源码了

简单工厂模式在很多地方都在使用,

  • 比如日历类Calendar.getInstance()方法

  • 或者logback中到 LoggerFactory 中有多个重载的方法 getLogger()

简单工厂的缺点就是,工厂类的职责相对过重,不易于扩展过于复杂的产品结构

工厂方法模式

  • 和简单工厂模式相比,工厂方法模式将生成具体产品的任务分发给具体的产品工厂,而不是由一个大工厂聚合生产

  • Phone 、XiaoMiPhone、HuaWeiPhone 类的不变

  • 新增抽象工厂类、小米工厂类、华为工厂类即可

  • 总工厂接口

public interface PhoneFactory {
    Phone makePhone();
}
  • 小米工厂类

public class XiaoMiFactory implements PhoneFactory { 
  @Override
  public Phone makePhone() {
  // 这里的方式是:;若生产何种产品完全由工厂决定,则这里不应该传入控制生产的参数。
  // 如果消费者知道自己想要什么产品,可以入参,用参数来区别对待生产不同的产品。像简单工厂模式一一致
  return new XiaoMiPhone();
  }
}
  • 华为工厂类

public class HuaWeiFactory implements PhoneFactory { 
  @Override
  public Phone makePhone() {
  // 这里的方式是:;若生产何种产品完全由工厂决定,则这里不应该传入控制生产的参数。
  // 如果消费者知道自己想要什么产品,可以入参,用参数来区别对待生产不同的产品。像简单工厂模式一一致
  return new HuaWeiPhone();
  }
}
  • 用户需求方

public class TestMain {
    public static void main(String[] args) {
        PhoneFactory  xiaoMiFactory = new XiaoMiFactory();
        PhoneFactory  huaWeiFactory = new HuaWeiFactory();
        Phone xiaomi = xiaoMiFactory.makePhone();
        Phone huawei = huaWeiFactory.makePhone();
        xiaomi.make();
        huawei.make();
    }
}
  • 类图如下所示

工厂方法模式主要解决的是产品的扩展问题

  • 在简单工程模式中,最后我们使用反射的方式实现开闭原则

  • 但是如果没饿过课程的创建逻辑有区别的话,工厂的职责就会越加繁重,不利于维护

  • 根据单一职责原则,我们可以将职能进行划分

    • 最大的工厂只负责约束管理

    • 其下允许动态创建其他干实事的小工厂

    • 就比如富士康只负责谈需求,接单,产品验收

    • 但其下的子工厂或者找个外包工厂(自由扩展)来干活

  • 工厂方法模式和简单工厂的区别就在于

    • 简单工厂只有一个工厂,负责产品的创建和销售

    • 工厂方法模式,有一个最大的工厂负责制定规章制度,旗下有很多专一的小工厂来负责生产和销售

抽象工厂模式

  • 定义了一个 interface 用于创建相关或有依赖关系的对象簇,而无需指明具体的类

  • 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。

  • 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)

  • 将工厂抽象成两层,AbsFactory(抽象工厂) 和 具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。

  • 上面的工厂模式都是在围绕手机在生产,如果这个时候,我们添加一个PC领域进去该如何玩呢?

  • 手机制造顶级接口

public interface Phone {
    void make();
}
  • 小米手机制造商

public class XiaoMiPhone implements Phone {
    @Override
    public void make() {
        System.out.println("制造了一台小米手机");
    }
}
  • 华为手机制造商

public class HuaWeiPhone implements Phone {
    @Override
    public void make() {
        System.out.println("制造了一台华为手机");
    }
}
  • 笔记本制造顶级接口

public interface PC {
    void make();
}
  • 小米笔记本制造商

public class XiaoMiPC implements PC{
    @Override
    public void make() {
        System.out.println("生产了一台小米笔记本");
    }
}
  • 华为笔记本制造商

public class HuaWeiPC implements PC{
    @Override
    public void make() {
        System.out.println("生产了一台华为笔记本");
    }
}
  • 代工厂顶级接口,如果有一些公共的方法可以抽取,也可以使用抽象类来创建

public interface AbstractFactory {
    Phone makePhone();
    PC makePC();
}
  • 小米代工厂制造接口

public class XiaoMiFactory implements AbstractFactory {
    @Override
    public Phone makePhone() {
        // 这里的方式是:;若生产何种产品完全由工厂决定,则这里不应该传入控制生产的参数。
        // 如果消费者知道自己想要什么产品,可以入参,用参数来区别对待生产不同的产品。想简答工厂模式一一致
        return new XiaoMiPhone();
    }
​
    @Override
    public PC makePC() {
        // 这里的方式是:;若生产何种产品完全由工厂决定,则这里不应该传入控制生产的参数。
        // 如果消费者知道自己想要什么产品,可以入参,用参数来区别对待生产不同的产品。想简答工厂模式一一致
        return new XiaoMiPC();
    }
}
  • 华为代工厂制造接口

public class HuaWeiFactory implements AbstractFactory {
    @Override
    public Phone makePhone() {
        // 这里的方式是:;若生产何种产品完全由工厂决定,则这里不应该传入控制生产的参数。
        // 如果消费者知道自己想要什么产品,可以入参,用参数来区别对待生产不同的产品。想简答工厂模式一一致
        return new HuaWeiPhone();
    }
​
    @Override
    public PC makePC() {
        // 这里的方式是:;若生产何种产品完全由工厂决定,则这里不应该传入控制生产的参数。
        // 如果消费者知道自己想要什么产品,可以入参,用参数来区别对待生产不同的产品。想简答工厂模式一一致
        return new HuaWeiPC();
    }
}
  • 需求方

public class TestMain {
    public static void main(String[] args) {
        AbstractFactory xiaoMiFactory = new XiaoMiFactory();
        AbstractFactory huaWeiFactory = new HuaWeiFactory();
        Phone xiaomi = xiaoMiFactory.makePhone();
        PC xiaomiPC = xiaoMiFactory.makePC();
        Phone huawei = huaWeiFactory.makePhone();
        PC huaweiPC = huaWeiFactory.makePC();
        xiaomi.make();
        xiaomiPC.make();
        huawei.make();
        huaweiPC.make();
    }
}
  • 类图如下所示

  • 此时,如果我们觉得手机和笔记本都已经玩腻了,想进军造车行业

    • 定义造成顶级接口

    • 定义造车品牌实现接口,比如小鹏汽车,蔚来汽车等

    • 此时增加代工顶级接口一个允许生产汽车的行为,并写一个汽车代工厂即可工厂

    • 扩展性就大大的增加了

抽象工厂非常完美清晰地描述这样一层复杂的关系

  • 小米公司可以生产手机和笔记本电脑

  • 华为公司可以生成手机和笔记本电脑

  • 如果此时我们还想继续追加他的功能职责,比如生产无人机

    • 这个时候就要定义一个无人机的顶级接口

    • 然后小米和华为都要再定义一个无人机的实现类

    • 然后再在代工厂顶级接口中新增一个生产无人机的方法(开闭原则被破坏)

    • 最后小米和华为的Factory,重写代工厂顶级接口中方法,实现无人机的生产(开闭原则被破坏)

    • 使用的时候,如上方使用代码差异无二

  • 因此抽象工程模式也是有很大缺点的,维护难度加大,理解难度加大

    • 扩展时 - > 代工厂顶级接口需要维护

    • 扩展时 - > 代工厂顶级接口的实现工厂也要维护实现对应方法

  • 但是在实际应用中,我们新增一个功能职责的周期是很长的,只要不是频繁新增,这种设计模式仍然适合我们

  • 抽象工厂模式在Spring中的应用是最为广泛的一种设计模式

工厂模式小结

  • 工厂模式的意义

    • 将实例化对象的代码提取出来,放到一个类中统一管理维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。

  • 三种工厂模式 (简单工厂模式、工厂方法模式、抽象工厂模式)

  • 设计模式的依赖抽象原则

    • 创建对象实例时,不要直接 new 类, 而是把这个 new 类的动作放在一个工厂的方法中,并返回

    • 不要让类继承具体类,而是继承抽象类或者是实现 interface(接口)

    • Ø 不要覆盖基类中已经实现的方法。

.

posted @ 2021-10-27 22:19  鞋破露脚尖儿  阅读(77)  评论(0编辑  收藏  举报