本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
其他设计模式介绍
创建型:
工厂方法
抽象工厂
原型
结构型:
适配器
桥接模式
组合模式
装饰模式
外观模式
享元模式
代理模式
行为型:
职责链
命令
解释器
迭代器
中介者
备忘录
状态模式
策略模式
模板方法
访问者
定义
是围绕一个超级工厂创建其他工厂,提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类;具体的工厂负责实现具体的产品实例
抽象工厂模式与工厂方法模式最大的区别:抽象工厂中每个工厂可以创建多种类的产品;而工厂方法每个工厂只能创建一类。
主要作用
允许使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么,这样就可以从具体产品中被解耦。
解决的问题
工厂方法模式的缺点,每个工厂只能创建一类产品,而抽象工厂可以创建多种类的产品。
UML类图
模式组成
组成(角色) | 关系 | 作用 |
---|---|---|
抽象产品族(AbstractProduct) | 抽象产品的父类 | 描述抽象产品的公共接口 |
抽象产品(Product) | 具体产品的父类 | 描述具体产品的公共接口 |
具体产品(Concrete Product) | 抽象产品的子类;工厂类创建的目标类 | 描述生产的具体产品 |
抽象工厂(Creator) | 具体工厂的父类 | 描述具体工厂的公共接口 |
具体工厂(Concrete Creator) | 抽象工厂的子类;被外界调用 | 描述具体工厂;实现FactoryMethod工厂方法创建产品的实例 |
使用步骤
步骤1: 创建抽象工厂类,定义具体工厂的公共接口;
步骤2: 创建抽象产品族类 ,定义抽象产品的公共接口;
步骤3: 创建抽象产品类 (继承抽象产品族类),定义具体产品的公共接口;
步骤4: 创建具体产品类(继承抽象产品类) & 定义生产的具体产品;
步骤5: 创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;
步骤6: 客户端通过实例化具体的工厂类,并调用其创建不同目标产品的方法创建不同具体产品类的实例
实例讲解
接下来我用一个实例来对抽象工厂模式进行更深一步的介绍。
实例概况
- 背景:小成有两间塑料加工厂(A厂仅生产容器类产品;B厂仅生产模具类产品);随着客户需求的变化,A厂所在地的客户需要也模具类产品,B厂所在地的客户也需要容器类产品;
- 冲突:没有资源(资金+租位)在当地分别开设多一家注塑分厂
- 解决方案:在原有的两家塑料厂里增设生产需求的功能,即A厂能生产容器+模具产品;B厂间能生产模具+容器产品。
即抽象工厂模式
使用步骤
步骤1: 创建抽象工厂类,定义具体工厂的公共接口
abstract class Factory{
public abstract Product ManufactureContainer();
public abstract Product ManufactureMould();
}
步骤2: 创建抽象产品族类 ,定义具体产品的公共接口;
abstract class AbstractProduct{
public abstract void Show();
}
步骤3: 创建抽象产品类 ,定义具体产品的公共接口;
//容器产品抽象类
abstract class ContainerProduct extends AbstractProduct{
@Override
public abstract void Show();
}
//模具产品抽象类
abstract class MouldProduct extends AbstractProduct{
@Override
public abstract void Show();
}
步骤4: 创建具体产品类(继承抽象产品类), 定义生产的具体产品;
//容器产品A类
class ContainerProductA extends ContainerProduct{
@Override
public void Show() {
System.out.println("生产出了容器产品A");
}
}
//容器产品B类
class ContainerProductB extends ContainerProduct{
@Override
public void Show() {
System.out.println("生产出了容器产品B");
}
}
//模具产品A类
class MouldProductA extends MouldProduct{
@Override
public void Show() {
System.out.println("生产出了模具产品A");
}
}
//模具产品B类
class MouldProductB extends MouldProduct{
@Override
public void Show() {
System.out.println("生产出了模具产品B");
}
}
步骤5: 创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;
//A厂 - 生产模具+容器产品
class FactoryA extends Factory{
@Override
public Product ManufactureContainer() {
return new ContainerProductA();
}
@Override
public Product ManufactureMould() {
return new MouldProductA();
}
}
//B厂 - 生产模具+容器产品
class FactoryB extends Factory{
@Override
public Product ManufactureContainer() {
return new ContainerProductB();
}
@Override
public Product ManufactureMould() {
return new MouldProductB();
}
}
步骤6: 客户端通过实例化具体的工厂类,并调用其创建不同目标产品的方法创建不同具体产品类的实例
//生产工作流程
public class AbstractFactoryPattern {
public static void main(String[] args){
FactoryA mFactoryA = new FactoryA();
FactoryB mFactoryB = new FactoryB();
//A厂当地客户需要容器产品A
mFactoryA.ManufactureContainer().Show();
//A厂当地客户需要模具产品A
mFactoryA.ManufactureMould().Show();
//B厂当地客户需要容器产品B
mFactoryB.ManufactureContainer().Show();
//B厂当地客户需要模具产品B
mFactoryB.ManufactureMould().Show();
}
}
结果:
生产出了容器产品A
生产出了容器产品B
生产出了模具产品A
生产出了模具产品B
优点
- 降低耦合
抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展; - 更符合开-闭原则
新增一种产品类时,只需要增加相应的具体产品类和相应的工厂子类即可
简单工厂模式需要修改工厂类的判断逻辑
- 符合单一职责原则
每个具体工厂类只负责创建对应的产品
简单工厂中的工厂类存在复杂的switch逻辑判断
- 不使用静态工厂方法,可以形成基于继承的等级结构。
简单工厂模式的工厂类使用静态工厂方法
缺点
抽象工厂模式很难支持新种类产品的变化。
这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则。
对于新的产品族符合开-闭原则;对于新的产品种类不符合开-闭原则,这一特性称为开-闭原则的倾斜性。