抽象工厂模式(Abstract Factory)概念
抽象工厂模式是对象的创建模式,它是工厂方法模式的进一步推广。
它为客户端提供一个创建一组相关或相互依赖对象的接口,且访问类无需指定所要产品的具体类型就能得到同一族的、不同等级的产品。
工厂方法模式只能生产一个等级的产品(例如休闲裤、西库),而此处的抽象工厂模式可以生产多个等级的产品(如休闲裤、西裤;休闲上衣、西装上衣)。
将同一个具体工厂生产的位于不同等级的同一组产品称为一个产品族。如下图所示,横轴是产品等级,也就是同一类产品;纵轴是产品族,同一个族的产品来自同一个具体工厂。
例如,假设有两个操作系统:windows、linux,那么:
- 1)windows下的按钮、linux下的按钮背后实现不同,但都是按钮,属于第1个产品等级;
- 2)windows下的文本框、linux下的文本框背后实现不同,但都是文本框,属于第2个产品等级;
- 3)windows下的多选框、linux下的多选框背后实现不同,但都是多选框,属于第3个产品等级;
- 4)windows属于第1个产品族,其中包含3个具体产品:windows下的按钮、windows下的文本框、windows下的多选框,这3个具体产品个由第1个具体工厂来来创建;
- 5)linux属于第2个产品族,其中包含3个具体产品:linux下的按钮、linux下的文本框、linux下的多选框,这3个具体产品个由第2个具体工厂来来创建。
所以,最后算下来,就有3个产品等级(按钮、文本框、多选框),2个产品族(windows、linux),其中每个产品等级中有2个具体产品,每个产品族中有3个具体产品。
每个产品等级中包含的具体产品数量就是产品族的数量,每个产品族中包含的产品数量等于产品等级的数量。
抽象工厂模式的结构
抽象工厂模式涉及如下角色:
- 抽象工厂(Abstract Factory):提供了创建产品的接口,其中提供了创建同一产品族中不同等级的产品的多个方法。如,方法1生产上衣、方法2生产裤子、方法3生产鞋子。
- 具体工厂(Concrete Factory):实现抽象工厂中的抽象方法,完成具体产品的创建。这个角色在客户端的调用下创建产品的实例。
- 抽象产品(Abstract Product):定义了产品的规范,描述了产品的主要特性和功能。抽象工厂模式有多个抽象产品,可以每一个产品等级定义一个抽象产品。
- 具体产品(Concrete Product):实现了抽象产品所定义的抽象方法(接口),一个具体工厂可以创建多个具体产品。
示例
本示例中,生产西装上衣和西裤、休闲上衣和休闲裤,其中:
- 西装作为一个产品族,休闲装作为另外一个产品族
- 上衣作为一个产品等级,裤子作为另外一个产品等级
- 西装具体工厂负责生产西装上衣和西裤,休闲装具体工厂负责生产休闲上衣和休闲裤
类图:
源码:
package com.pattern.abstractfactory;
// 上衣
public interface Top {
void show();
}
package com.pattern.abstractfactory;
// 西装上衣
public class SuitJacket implements Top {
@Override
public void show() {
System.out.println("西装上衣");
}
}
package com.pattern.abstractfactory;
// 休闲上衣
public class CasualTop implements Top {
@Override
public void show() {
System.out.println("休闲上衣");
}
}
package com.pattern.abstractfactory;
// 裤子
public interface Pants {
void show2();
}
package com.pattern.abstractfactory;
// 西裤
public class DressPants implements Pants {
@Override
public void show2() {
System.out.println("西裤");
}
}
package com.pattern.abstractfactory;
// 休闲裤
public class CasualPants implements Pants {
@Override
public void show2() {
System.out.println("休闲裤");
}
}
package com.pattern.abstractfactory;
// 生产衣服的抽象工厂
public interface ClothesAbstractFactory {
// 生产裤子
Pants creatPants();
// 生产上衣
Top createTop();
}
package com.pattern.abstractfactory;
// 生产西装的具体工厂类
public class SuitFactory implements ClothesAbstractFactory {
@Override
public Pants creatPants() {
// 创建西裤的实例
return new DressPants();
}
@Override
public Top createTop() {
// 创建西装上衣的实例
return new SuitJacket();
}
}
package com.pattern.abstractfactory;
// 生产休闲装的具体工厂
public class CasualFactory implements ClothesAbstractFactory {
@Override
public Pants creatPants() {
// 创建休闲裤的实例
return new CasualPants();
}
@Override
public Top createTop() {
// 创建休闲上衣的实例
return new CasualTop();
}
}
测试类:
package com.pattern.abstractfactory;
public class Client {
public static void main(String[] args) {
// 创建生产西装的工厂实例
ClothesAbstractFactory suitFactory = new SuitFactory();
// 生产西装上衣
Top suitJacke = suitFactory.createTop();
// 生产西裤
Pants dressPants = suitFactory.creatPants();
suitJacke.show();
dressPants.show2();
// 创建生产休闲装的工厂实例
ClothesAbstractFactory casualFactory = new CasualFactory();
// 生产休闲装上衣
Top casualTop = casualFactory.createTop();
// 生产休闲裤
Pants casualPants = casualFactory.creatPants();
casualTop.show();
casualPants.show2();
}
}
运行输出:
西装上衣
西裤
休闲上衣
休闲裤
抽象工厂模式遵循开-闭原则的情况
新增产品族:在产品等级结构数目不变的情况下,增加新的产品族,意味着每个产品等级中增加一个或多个具体的产品类,并且新增一个具体工厂类,已经存在的产品和工厂都不需要修改,满足对扩展开放,对修改关闭的开-闭原则。
新增产品等级结构:在产品族数目不变的情况下,增加新的产品等级,已有的产品不需要改变,需要增加一个与现在产品等级平行的新的产品等级结构。要做到这一点,需要修改所有工厂角色,给每个工厂类增加一个新的工厂方法,这是违背对扩展开放,对修改关闭的开-闭原则的。
抽象工厂模式的优缺点
优点:
- 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。即客户端只消费一个产品族中的对象。
缺点:
- 当需要新增一个产品等级结构时,所有的工厂类(包括抽象工厂和具体工厂)都需要修改。
抽象工厂模式的使用场景
- 当需要创建的对象是一系列相关联或相互依赖的产品族时。
- 系统中有多个产品族,但每次只使用其中的一族产品。
- 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。