设计模式之——抽象工厂模式
设计模式之——工厂方法模式最后讲到,工厂方法模式的缺点是如果产品种类过多,需要生产大量的工厂类。同时,由于每个产品种类还分产品族,比如,汽车品牌大众的产品组有跑车类型、家庭类型和商用类型的车;奔驰也有跑车类型、家庭类型和商用类型的车......那么大众、奔驰和其他品牌的想同类型(比如跑车类型)的车可以组成一个产品组跑车类型。这种情况,就适合使用抽象工厂模式。
1 定义
抽象工厂模式:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
抽象工厂模式通用类图2 通用代码示例
2.1 产品类
- 抽象产品类A
AbstractProductA,类似于品牌A,例如大众车品牌。
public abstract class AbstractProductA {
/**
* 产品A的共享方法,对所有的继承子类方法生效
*/
public void sharedMethod() {
}
/**
* 产品A的抽象方法,需要各个具体实现类进行实现
*/
public abstract void method();
}
具体的产品实现类:
ConcreteProductA1: 类似于大众车的跑车类型。
public class ConcreteProductA1 extends AbstractProductA {
@Override
public void method() {
//业务处理逻辑
}
}
ConcreteProductA2: 类似于大众车的家庭类型。
public class ConcreteProductA2 extends AbstractProductA {
@Override
public void method() {
//业务处理逻辑
}
}
- 抽象产品类B
AbstractProductB,类似于品牌B,例如奔驰车品牌。
public abstract class AbstractProductB {
/**
* 产品B的共享方法,对所有的继承子类方法生效
*/
public void sharedMethod() {
}
/**
* 产品B的抽象方法,需要各个具体实现类进行实现
*/
public abstract void method();
}
具体的产品实现类:
ConcreteProductB1: 类似于奔驰车的跑车类型。
public class ConcreteProductB1 extends AbstractProductB {
@Override
public void method() {
//业务处理逻辑
}
}
ConcreteProductB2: 类似于奔驰车的家庭类型。
public class ConcreteProductB2 extends AbstractProductB {
@Override
public void method() {
//业务处理逻辑
}
}
2.2 工厂实现
- 抽象工厂类
有N个产品品牌,在抽象工厂类中就应该有N个创建方法。
public abstract class AbstractCreatorFactory {
/**
* 声明生成产品A的方法
*
* @return 产品A实例
*/
public abstract AbstractProductA createProductA();
/**
* 声明生成产品B的方法
*
* @return 产品A实例
*/
public abstract AbstractProductB createProductB();
}
- 具体工厂实现类
具体创建一个产品,由具体的工厂实现类来完成。有M个产品族就应该有M个实现工厂类,在每个具体工厂中,实现不同产品族的生产任务。
产品族1的具体工厂(如跑车工厂):
public class ConcreteCreatorFactory1 extends AbstractCreatorFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB1();
}
}
产品族2的具体工厂(如家庭车工厂):
public class ConcreteCreatorFactory2 extends AbstractCreatorFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB2();
}
}
2.3 客户类
public class Client {
public static void main(String[] args) {
//定义两个工厂
AbstractCreatorFactory factory1 = new ConcreteCreatorFactory1();
AbstractCreatorFactory factory2 = new ConcreteCreatorFactory2();
//产生A族的对象(如跑车)
//大众跑车
AbstractProductA productA1 = factory1.createProductA();
//奔驰跑车
AbstractProductA productA2 = factory2.createProductA();
//产生B族的对象(如家庭车)
//大众家庭车
AbstractProductB productB1 = factory1.createProductB();
//奔驰家庭车
AbstractProductB productB2 = factory2.createProductB();
}
}
在场景类中,所有方法只与抽象类有关系。对于客户端来说,只要知道工厂方法就可以产生一个一个产品,而无需关心实现类。
抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类,抽象工厂模式较好的实现了“开放-封闭”原则,是三个模式中较为抽象,并具一般性的模式。
但是,我们在使用中要注意使用抽象工厂模式的条件。
3 抽象工厂模式的优缺点
3.1 优点
- 封装性
高层模块不需要关心产品的实现类,具体的对象是通过工厂创建的。高层只关心工厂和抽象产品,而不关注具体实现。 - 产品族内的约束为非公开状态
产生产品族内的产品的过程,对高层调用来说是透明的、无需关注的。
3.2 缺点
抽象工厂模式最大的缺点是:产品族扩展非常困难。
以上面通用代码示例为例,如果要增加一个品牌C,则工厂类重要添加方法AbstractProductC createProductC()
,同时所有的具体工厂类也需要修改,严重违反了开闭原则。
4 抽象工厂模式使用场景
4.1 使用场景
抽象工厂模式的使用场景:一个对象族(或一组没有任何关系的对象)都有相同的约束,则可以使用抽象工厂模式。
4.2 注意事项
抽象工厂模式缺点是品牌扩展困难,但是产品族扩展是非常容易的。增加一个产品族只需要新增加一个工厂负责生产新增的产品族实现类即可。从增加产品族的角度来看,抽象工厂模式是符合开闭原则的。
也就是说抽象工厂模式:横向扩展容易,纵向扩展困难。
4.3 最佳实践
在未来横向扩展较多的场景中,可以使用抽象工厂模式来设计框架,满足未来扩展需求。