GoF23:Factory-工厂
关键字 new:用于实例化一个具体的类。
缺点:在客户端直接使用 new 创建类,属于面向实现编程。
- 耦合度高:调用者必须知道所有可用的产品实现类,才可以根据需求获取实例。
- 可维护性差:当需求发生改变时,需要修改原有代码。
工厂(Factory):
处理创建对象的细节,实现创建者和调用者的分离。
类型:
- 简单工厂模式(静态工厂):编程习惯
- 工厂方法模式:对象的实例化延迟到子类。
- 抽象工厂模式:工厂的工厂。
1、简单工厂
1.1、定义
简单工厂(静态工厂):
是一种编程习惯,而不是真正意义上的设计模式。
- 做法:
- 封装创建对象的代码,实现创建者和调用者的分离。
- 通常将简单工厂中创建对象的方法声明为
static
,aka 静态工厂。
- 特点:
- 调用者只需传入正确参数即可获取所需产品对象,无需知道对象创建细节。
- 违反开闭原则:若需求改变(如增加或减少产品),需修改简单工厂的代码。
类图
应用
-
JDK 日期类:如 java.text.DateFormat
-
Java 加密技术:
-
获取不同加密算法的密钥生成器
-
创建密码器
KeyGenerator keyGen = KeyGenerator.getInstance("DESede"); Cipher cp = Cipher.getInstance("DESede");
-
1.2、示例
1.2.1、产品 - Pizza
抽象类:比萨
public abstract class Pizza {
private String name;
private Cheese cheese;
private Clam clam;
private Dough dough;
private Pepperoni pepperoni;
private Sauce sauce;
private Veggies[] veggies;
public void prepare() {...}
public void bake() {...}
public void cut() {...}
public void box() {...}
}
子类:不同的比萨类型。
// 芝士
public class CheesePizza extends Pizza{
...
}
// 意大利辣香肠
public class PepperoniPizza extends Pizza{
...
}
1.2.2、客户端 - PizzaStore
基于不同 Pizza 类型,创建并做加工处理。
public class PizzaStore {
private Pizza pizza();
public Pizza orderPizza(String type) {
// 创建产品
switch (type) {
case "cheese":
pizza = new CheesePizza();
break;
case "pepperoni":
pizza = new PepperoniPizza();
break;
default:
pizza = null;
}
// 处理产品
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
1.2.3、工厂 - PizzaFactory
orderPizza() 分析:
该方法的核心功能是处理产品 Pizza,但代码中耦合了对产品的创建。
- 引入简单工厂,专门负责产品 Pizza 的创建。
- 需求变化只需修改简单工厂的逻辑,不会影响客户端代码。
代码示例
-
简单工厂:
public class PizzaFactory { public static Pizza createPizza(String type) { Pizza pizza; // 创建产品 switch (type) { case "cheese": pizza = new CheesePizza(); break; case "pepperoni": pizza = new PepperoniPizza(); break; default: pizza = null; } return pizza; } }
-
客户端:去掉创建产品的逻辑。
public class PizzaStore { private Pizza pizza(); public Pizza orderPizza(String type) { // 获取产品 PizzaFactory.createPizza(type); // 处理产品 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } }
2、工厂方法
2.1、定义
工厂方法:
将对象的实例化推迟到子类,每个子类相当于一个工厂。
- 做法:基于继承或实现。
- 定义一个创建对象的接口,由子类决定要实例化的类。
- 通常工厂方法会根据不同入参创建不同的对象,aka 参数化工厂方法。
- 说明:
- 工厂方法创建的对象是同一个产品等级结构。
- 针对参数化工厂方法,通常定义静态变量、枚举类来作为参数类型,以避免拼写错误。
- 遵守的设计原则:开闭、里氏替换、依赖倒置。
类图
应用
示例:JDBC
Connection conn = DriverManager
.getConnection("jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=DB;user=sa;password=");
Statement statement = conn.createStatement();
2.2、示例
2.2.1、PizzaStore
需求:PizzaStore 改为抽象类型,允许不同类型的子类(Pizza 加盟店)。
不同子类使用的产品 Pizza 不同。
public abstract class PizzaStore {
...
}
实现类:不同地区的 PizzaStore
- 对于同一个 Pizza,芝加哥和纽约的风味可能不同。
- 如 CheesePizza 类,单个类已无法满足需求,需要分为 ChicagoCheesePizza 和 NYCheesePizza。
2.2.2、工厂方法
PizzaStore 抽象类:
定义创建产品 Pizza 的抽象方法,由子类(不同地区的 PizzaStore)实现其逻辑。
public abstract class PizzaStore {
Pizza orderPizza(String type) {
// 获取产品
Pizza pizza = this.createPizza(type);
// 处理产品
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
// 工厂方法
abstract Pizza createPizza(String type);
}
PizzaStore子类——即加盟店
-
实现类 1:
public class ChicagoPizzaStore extends PizzaStore{ @Override Pizza createPizza(String type) { Pizza pizza; // 判断Pizza类型,获取Pizza switch (type) { case "cheese": pizza = new ChicagoCheesePizza(); break; case "pepperoni": pizza = new ChicagoPepperoniPizza(); break; default: pizza = null; } return pizza; } }
-
实现类 2:
public class NyPizzaFactory extends PizzaSimpleFactory{ @Override public Pizza createPizza(String type) { Pizza pizza; // 判断Pizza类型,获取Pizza switch (type) { case "cheese": pizza = new NYCheesePizza(); break; case "pepperoni": pizza = new NYPepperoniPizza(); break; default: pizza = null; } return pizza; } }
3、抽象工厂
3.1、定义
抽象工厂
- 做法:基于类的组合。
- 定义一个创建工厂的接口,具体工厂用于创建相关或依赖的产品。
- 通常使用工厂方法模式来实现具体工厂。
- 说明:
- 抽象工厂创建的对象是同一个产品族(多个相关的产品等级结构)。
- 开闭原则的倾斜性:抽象工厂模式存在以下场景,需要进行权衡。
- 遵守开闭原则:对于产品族的扩展(即增加具体工厂),遵守。
- 违反开闭原则:对于产品等级结构的扩展(即增加新的产品),违反。
类图
3.2、对比
- 简单工厂:
- 存在一个简单工厂类,负责所有具体产品的创建。
- 创建的对象是同一个产品类型。
- 工厂方法:
- 存在一个工厂方法接口 + 多个实现类,子类负责实例化。
- 基于继承/实现的方式创建对象。
- 创建的对象是同一个产品等级结构。
- 抽象工厂:
- 存在一个抽象工厂接口 + 多个工厂实现类。
- 基于组合的方式创建对象。
- 创建的对象是同一个产品族(多个相关的产品等级结构)