抽象工厂模式的定义
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类
读起来很抽象,很晦涩难懂,程序员就得用程序员的角度去理解问题,代码说明一切。不过在说明抽象工厂模式之前,首先需要理解两个概念:产品族和产品等级
产品族和产品等级
产品族:简单的说,就是一个工厂里生产的所有产品的聚集。
产品等级:也就是说不同工厂生产的同一产品。
下面两张图形象的说明了这两个概念
(以上图片摘自刘伟的博客)
横向的表示不同产品,但是是同一工厂生产的,所以是产品族;纵向的都是同一种产品,但是不是同一个工厂生产的,所以形成了产品等级。举个简单的例子,美的生产冰箱、空调、洗衣机,海尔也生产冰箱、空调、洗衣机,海信也生产冰箱、空调、洗衣机。那么每个厂家的产品构成了产品族,不同厂家的冰箱、空调、洗衣机则形成产品等级。
抽象工厂的核心
对于上述的例子中,如果采用简单工厂的话该怎么写?显然,每个产品都得有一个工厂,美的冰箱工厂.java
、美的空调工厂.java
、美的洗衣机工厂.java
、海尔冰箱工厂.java
、海尔空调工厂.java
(这里使用中文只是为了方便演示)。。。这会形成类爆炸,我们希望用户知道:如果他知道美的工厂里有冰箱,那么直接通过美的工厂取出冰箱而不是通过美的冰箱工厂取出冰箱。这就避免了大量的类的创建,这也是抽象工厂模式的核心思想:通过将统一产品族的产品放在同一个工厂从而避免大量类的创建
一个简单的例子
还是以上面的例子作为演示,首先是一个抽象的工厂类以及产品的基类
public abstract class 电器工厂 {
public abstract 冰箱 获取冰箱();
public abstract 空调 获取空调();
public abstract 洗衣机 获取洗衣机();
}
public class 冰箱 {
public void doSomething() {
System.out.println("我是冰箱");
}
}
public class 空调 {
public void doSomething() {
System.out.println("我是空调");
}
}
public class 洗衣机 {
public void doSomething() {
System.out.println("我是洗衣机");
}
}
public class 美的冰箱 extends 冰箱{
public void doSomething() {
System.out.println("我是美的冰箱");
}
}
....
省略其他的一些类
那么每个工厂的实现将是下述所示
public class 美的工厂 extends 电器工厂 {
public abstract 冰箱 获取冰箱() {
return new 美的冰箱();
}
public abstract 空调 获取空调() {
return new 美的空调();
}
public abstract 洗衣机 获取洗衣机() {
return new 美的洗衣机();
}
}
这样在调用的时候只要 new 一个具体的工厂,那么就可以从这些工厂来取出产品族里的任何一个产品
抽象工厂模式的优缺点
优点是显而易见的:相比简单工厂,能够大大减少类的创建,同时对于同一产品族来说,新增一个工厂不会改变客户端代码的调用结果,也是符合开闭原则的。
缺点呢也是显而易见的:如果产品族里新增或者删除产品的话,那么就得修改每个工厂的实现,也就是产品等级的变化会严重影响类的修改,这时候就不符合开闭原则。
所以,综上,抽象工厂比较适用于产品族比较固定的场合,或者说产品族更新的频率比较小,如果频繁的变动,那么应当考虑使用其他的模式进行替换。
以上