5.创建型模式(工厂)
- 2021 年 10 月 10 日
- 筆記
1.工厂模式简述
- 基本思想:凡是需要生成复杂对象的地方,都可以尝试考虑工厂模式来代替
- 复杂对象:类的构造函数参数过多等对类的构造有影响的情况
- 定义:一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类中。(创建与使用分离)
- 产品:被创建的对象
- 工厂:创建产品的对象
2.简单工厂模式
- 创建实例的方法常为静态方法(静态工厂方法模式)
- 应用场景: 产品种类较少的情况
优点:
1.工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责,很方便的创建出相应的产品。工厂和产品的职责区分明确。
2.客户端无需知道所创建具体产品的类名,只需知道参数即可。
3.也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类。
缺点:
1.简单工厂模式的工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。且工厂类代码会非常臃肿,违背高聚合原则。
2.使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
3.系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂
4.简单工厂模式使用了 static 工厂方法,造成工厂角色无法形成基于继承的等级结构。
2.1结构与实现
- 简单工厂SimpleFactory:简单工厂模式的核心,负责实现创建所有实例的内部逻辑。其创建产品类的方法可直接被外界调用以创建所需产品对象。
- 抽象产品Product:简单工厂创建的所有对象的父类,负责描述所有实例公有的公共接口
- 具体产品ConcreteProduct:简单工厂模式的创建目标
示例:
//简单工厂
public class EasyFactory {
public static void main(String[] args) {
Product a = EasyFactory.makeProduct(1);
a.show();
}
public static Product makeProduct(int kind) {
if (kind == 1) {
return new Concrete1();
} else {
return new Concrete2();
}
}
}
//抽象产品
interface Product{
void show();
}
//具体产品1
class Concrete1 implements Product {
@Override
public void show() {
System.out.println("产品1");
}
}
//具体产品2
class Concrete2 implements Product {
@Override
public void show() {
System.out.println("产品2");
}
}
3.工厂模式
- 基于简单工厂模式,使系统在不修改源代码情况下引进新产品,符合开闭原则
- 优点
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
- 灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。
- 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。
- 缺点
- 类的个数容易过多,增加复杂度
- 增加了系统的抽象性和理解难度
- 抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。
- 应用场景:
- 客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。
- 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
- 客户不关心创建产品的细节,只关心产品的品牌
3.1 结构
- 抽象工厂:提供创建产品的接口,调用者通过其访问具体工厂的工厂方法以创建产品
- 具体工厂:实现抽象工厂中的抽象方法,完成具体产品创建
- 抽象产品:定义产品规范,描述产品主要特性和功能
- 具体产品:实现了抽象产品所定义的接口,由具体工厂创建,同具体工厂之间一一对应。
3.2 实现
- 创造可生成猪/马的工厂
点击查看工厂示例
public class Factory {
public static void main(String[] args) {
CreateAnimal factory1 = new CreateHorse();
Animal horse1 = factory1.getAnimal();
horse1.show();
}
}
//抽象产品,提供产品接口
interface Animal {
void show();
}
//具体产品1:马
class Horse implements Animal {
@Override
public void show() {
System.out.println("Horse!");
}
}
//具体产品2:猪
class Pig implements Animal {
@Override
public void show() {
System.out.println("Pig!");
}
}
//抽象工厂,提供产品生成方法
interface CreateAnimal {
Animal getAnimal();
}
//具体工厂1:生成马
class CreateHorse implements CreateAnimal{
@Override
public Animal getAnimal() {
return new Horse();
}
}
//具体工厂2:生成猪
class CreatePig implements CreateAnimal {
@Override
public Animal getAnimal() {
return new Pig();
}
}
4.抽象工厂模式
-
产品工厂与产品族解析
-
定义: 一种为访问类提供一个创建一组相关或相互依赖对象的接口,访问类无需指定索要产品具体类就得到同族不同等级的产品。
-
需满足条件
- 系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品
- 系统一次只可能消费某一族产品,即同族产品一起使用。
-
优点:
- 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
- 当需要产品族时,抽象工厂可以保证客户端始终只使用同一个产品的产品族。
- 抽象工厂增强了程序的可扩展性,当增加一个新的产品族时,不需要修改原代码,满足开闭原则。
-
缺点:产品族中需增加一个新产品时,所有工厂类都需修改,增加抽象性和理解难度。
-
适用场景
- 需创建的对象是一系列相互关联或相互依赖的产品族时(同一品牌的一系列产品)
- 系统中有多个产品族,但每次只使用其中某一族产品
- 系统中提供产品类库,且所有产品接口相同,客户端不依赖产品实例的创建细节和内部结构。
-
当系统中只存在一个等级结构产品时,抽象工厂模式将退化为工厂方法模式。
4.1 结构
- 抽象工厂:提供创建产品的接口,包含多个创建产品的方法,可创建多个不同等级的产品
- 具体工厂:实现抽象工厂中多个抽象方法,完成具体产品创建
- 抽象产品:定义产品规范,描述产品主要特性和功能
- 具体产品,实现抽象产品角色定义的接口,由具体工厂创建,一个具体工厂对应多个具体产品
4.2具体实例
- 创建农场模型,每个农场均有一种动物及其相关联植物。获取时需同时获取农场种动植物产品。
- 猴子农场:猴子+水果 奶牛农场:牛+草
点击农场代码
public class AbstractFactory {
public static void main(String[] args) {
Farm farm = new MonkeyFarm();
//获取工厂后无需获知产品细节
Animals David = farm.newAnimals();
Plants fruit1 = farm.newPlant();
David.show();
fruit1.show();
}
}
interface Plants {
void show();
}
class Grass implements Plants {
@Override
public void show() {
System.out.println("Grass!");
}
}
class Fruit implements Plants {
@Override
public void show() {
System.out.println("Fruit");
}
}
//抽象动物产品
interface Animals {
void show();
}
//具体产品--奶牛
class Cow implements Animals {
@Override
public void show() {
System.out.println("Cow!");
}
}
//具体产品-单例猴子
class Monkey implements Animals {
private static final Monkey instance = new Monkey();
private Monkey(){};
public static Monkey getInstance() {
return instance;
}
@Override
public void show() {
System.out.println("Monkey!");
}
}
//抽象工厂-农场:提供动物及植物
interface Farm {
Plants newPlant();
Animals newAnimals();
}
//具体奶牛工厂
class CowFarm implements Farm{
@Override
public Plants newPlant() {
return new Grass();
}
@Override
public Animals newAnimals() {
return new Cow();
}
}
//具体Monkey工厂
class MonkeyFarm implements Farm{
@Override
public Plants newPlant() {
return new Fruit();
}
@Override
public Animals newAnimals() {
return Monkey.getInstance();
}
}
5 工厂模式总结
- 简单工厂:不提供工厂的抽象接口,由一个工厂实例静态方法创建产品
- 工厂:基于简单工厂提供工厂的抽象接口
- 抽象工厂:基于工厂对一族产品进行工厂封装,实现一个工厂生产一族所有产品