1. 定义
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而
无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象创建型模式。
2. 结构
在抽象工厂模式中,每一个具体工厂都提供了多个工厂方法用于产生多种不同类型的产品,这些产品构成了一个产品族,抽象工厂模式结构如图所示:
- AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。(一族产品理解为海尔牌子的冰箱,洗衣机,电视机等)
- ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
- AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。(理解为不同牌子冰箱的父类)
- ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。
3. 代码实现
同一个品牌的这边给他算一个产品族,冰箱,电视算两个产品等级结构,一个具体的工厂实现类可以产生同一个品牌的不同的产品。
产品1接口
public interface Fridge {
void freeze();
}
产品1实现类1
public class HaierFridge implements Fridge {
@Override
public void freeze() {
System.out.println("海尔冰箱冰冻啦");
}
}
产品2实现类2
public class MediaFridge implements Fridge {
@Override
public void freeze() {
System.out.println("美的冰箱冰冻啦");
}
}
产品2接口
public interface Tv {
void watch();
}
产品2实现类1
public class HaierTv implements Tv {
@Override
public void watch() {
System.out.println("看海尔电视啦");
}
}
产品2实现类2
public class MediaTv implements Tv {
@Override
public void watch() {
System.out.println("看美的电视啦");
}
}
工厂接口
public interface Factory {
Tv getTv();
Fridge getFridge();
}
工厂实现类1
public class HaierFactory implements Factory {
@Override
public Tv getTv() {
return new HaierTv();
}
@Override
public Fridge getFridge() {
return new HaierFridge();
}
}
工厂实现类2
public class MediaFactory implements Factory {
@Override
public Tv getTv() {
return new MediaTv();
}
@Override
public Fridge getFridge() {
return new MediaFridge();
}
}
测试
public class Test {
public static void main(String[] args) {
//可以从配置文件中获得具体类名,通过反射获得相应的工厂类来实现其配置化
Factory factory1=new HaierFactory();
factory1.getTv().watch();
factory1.getFridge().freeze();
Factory factory2=new MediaFactory();
factory2.getTv().watch();
factory2.getFridge().freeze();
}
}
//看海尔电视啦
//海尔冰箱冰冻啦
//看美的电视啦
//美的冰箱冰冻啦
4. “开闭原则”的倾斜性(最大缺点)
在抽象工厂模式中,增加新的产品族很方便(如添加一个牌子的产品族),但是增加新的产品等级结构(添加洗衣机这个新的产品登记结构)很麻烦,抽象工厂模式的这种性质称为“开闭原则”的倾斜性。“开闭原则”要求系统对扩展开放,对修改封闭,通过扩展达到增强其功能的目的,对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括两方面:
- 增加产品族:对于增加新的产品族,抽象工厂模式很好地支持了“开闭原则”,只需要增加具体产品并对应增加一个新的具体工厂,对已有代码无须做任何修改。
- 增加新的产品等级结构:对于增加新的产品等级结构,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,违背了“开闭原则”。
5. 优缺点
- 优点
- 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么具体类被创建,只管调用工厂方法得到对应的产品接口即可。
- 将同一个产品族的产品在工厂实现类中放在了一块,使得客户端始终使用同一族中的对象。
- 增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。
- 缺点
- 增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则”。
6. 适用场景
- 用于对象的创建和使用的解耦,系统不依赖于产品类实例如何被创建、组合和表达的细节。
- 系统中有多于一个的产品族,而每次只使用其中某一产品族。可以通过配置文件等方式来使得用户可以动态改变产品族,也可以很方便地增加新的产品族。
- 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。(产品族需要具有一些共同约束,比如属于同一个牌子等)
- 产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的产品等级结构。
7. 个人理解
将具有共同约束的多个产品放在一个族里,工厂类中可以产生多个属于同一个产品族的产品,相比于工厂方法的每个产品一个工厂类来说可大量减少类的数量。缺点就是不可扩展其他产品种类。