我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”。在简单工厂模式中创建实例的方法通常为静态方法,因此简单工厂模式又叫作静态工厂方法模式。简单来说,简单工厂模式有一个具体的工厂类,可以生成多个不同的产品,属于创建型设计模式。简单工厂模式不在 GoF 23 种设计模式之列。简单工厂模式每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度,违背了“开闭原则”。
优点: ① 工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责,很方便的创建出相应的产品。工厂和产品的职责区分明确。 ② 客户端无需知道所创建具体产品的类名,只需知道参数即可。 ③ 也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类。
缺点: ① 简单工厂模式的工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。且工厂类代码会非常臃肿,违背高聚合原则。 ② 使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度 ③ 系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂 ④ 简单工厂模式使用了 static 工厂方法,造成工厂角色无法形成基于继承的等级结构。
有那么一天,收购了华为、小米、苹果,想要每家的新手机需要去自己去各家拿,地方还不一样。一怒之下收购了富士康,让他来生产其他手机,自己想要什么跟他说,造好了直接给你,不需要自己去。如下图所示,放弃了自己去 new 对象,交由工厂去创建好之后返回给自己。
/**
* @author Demo_Null
* @version 1.0
* @date 2020/12/24
*/
public class SimpleFactory {
public Phone getPhone(String name) {
// 参数合法性判断
if (null == name || 0 == name.length()) {
return null;
}
Phone phone = null;
// 创建对应的实例
switch (name) {
case "MI":
phone = new MI();
break;
case "HUAWEI":
phone = new HUAWEI();
break;
case "IPhone":
phone = new IPhone();
break;
default:
System.out.println("无法识别");
}
return phone;
}
}
工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现‘开闭原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。 工厂方法模式对简单工厂模式进行了抽象。有一个抽象的 Factory 类(可以是抽象类和接口),这个类将不再负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。
优点: ① 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。 ② 灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。 ③ 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。
缺点: ① 类的个数容易过多,增加复杂度 ② 增加了系统的抽象性和理解难度 ③ 抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。
工厂方法模式建议使用特殊的工厂方法代替对于对象构造函数的直接调用,即在工厂方法中使用 new。 乍看之下, 这种更改可能毫无意义: 我们只是改变了程序中调用构造函数的位置而已。 但是, 仔细想一下, 现在可以在子类中重写工厂方法, 从而改变其创建产品的类型。如下图所示,ConcreteProductA 和 ConcreteProductB 都必须实现 Product 接口, 该接口声明了一个名为 doStuff 的方法。 每个类都将以不同的方式实现该方法。 ConcreteCreatorA 类中的工厂方法返回 ConcreteCreatorA, 而 ConcreteCreatorB 类则返回 ConcreteCreatorB。