抽象工厂模式
2018年8月24日17:20:30
抽象工厂模式
定义
借我一只晨光的铅笔,明天就还给你。
现在我可以还你晨光的铅笔了,你早已不在了,明天还是明天。
抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。——《设计模式:可复用面向对象软件的基础》
使用场景
首先要来认识两个新概念:产品族和产品等级结构 。
产品族,是指不同产品等级结构中,功能相关的产品组成的家族。
产品等级结构, 即产品的继承结构,继承(或实现)同一抽象产品的具体产品属于同一产品等级结构。
在后面的代码示例中,晨光文具和真彩文具是两个产品族,继承(或实现)铅笔抽象产品的晨光铅笔和真彩铅笔是一个产品等级结构,继承(或实现)橡皮抽象产品的晨光铅笔和真彩铅笔是另一个产品等级结构。【这个我用了继承(或实现)是因为Java中有接口是实现的,抽象类是继承的,抽象产品既可以是接口,也可以是抽象类,为了不误导我自己,特意加上。】例子还有:Intel的主板、芯片组、CPU是一个产品族,AMD的主板、芯片组、CPU也是一个产品族,而这里有三个产品等级结构,分别是:主板、芯片组、CPU。
想代码示例的时候,想我们经常用的东西,就想到了文具,想到了晨光和真彩。查了一下,没想到小小文具,营业额超十亿。
现在我们的目标是先赚他一个亿,开一家博客园文具(产品族),产品等级结构呢,他们都有,我们直接继承(或实现)他们的抽象产品类就好了,多方便。这就是抽象工厂模式的好处。增加一个产品族,不用破坏原来代码结构,符合开闭原则。
但是只有老产品,没有什么竞争力,要不我们增加一个新产品即新的产品等级结构,暂时就是码农作弊专用智能笔,帮你轻松应对笔试,这时我们就要在博客园文具(产品族)添加新成员,需要在博客园文具具体工厂类中添加相关创建新产品的代码,不符合开闭原则。这就是抽象工厂模式的缺点了。
综上所述,结合其他情况,以下情况可以使用抽象工厂模式:
1、一个系统不应当依赖于产品实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
2、系统有多于一个的产品,且每次只使用其中一个产品族。
3、属于同一产品族的产品将在一起使用,这一约束应该在系统设计中体现出来。
4、所有产品以自己继承(或实现)的接口出现,从而客户端不依赖于具体实现。
第1点,毋庸置疑。第2点和第3点,说的是我选择晨光文具,我使用的就是晨光的铅笔就要使用晨光的橡皮,要配套使用,不能是我使用了晨光的铅笔却使用真彩的橡皮。这个约束在这个例子看起来有点牵强,但是想一下这样的场景:期末考试要同一文具,有两种选择,一种是晨光,一种是真彩,他们是配套的,晨光的铅笔配晨光的橡皮,真彩的铅笔配真彩的橡皮,这样就舒服了。第4点,面向接口编程,降低耦合。
第2点和第3点,用上面提到的Intel、AMD产品族更贴切,Intel的CPU是无法和AMD的主板匹配的,AMD的CPU也无法和Intel的主板匹配,所以组装电脑的时候,就默认有这个约束:只能使用同一个产品族中的产品。
关于抽象工厂模式的起源,是用于创建分属于不同操作系统的视窗构建。比如:命令按键(Button)与文字框(Text)都是视窗构建,在UNIX操作系统的视窗环境和Windows操作系统的视窗环境中,这两个构建有不同的本地实现,它们的细节有所不同。视窗构建时,只能选择一个操作系统的Button和Text,如果不是,两个操作系统都用不了,我要这视窗有何用?
角色
抽象工厂角色(Abstract Factory):具体工厂(产品族)公共接口
具体工厂角色(Concrete Factory):产品族
抽象产品角色(Abstract Product):产品等级结构
具体产品角色(Concrete Product):产品
图示
代码示例
代码示例类依赖关系图:
抽象工厂角色(AbstractFactory.java)
public interface AbstractFactory {
public Pencil createPencil();
public Eraser createEraser();
}
具体工厂角色(ChenGuangFactory.java、TrueColorFactory.java)
// 晨光工厂
public class ChenGuangFactory implements AbstractFactory {
@Override
public Pencil createPencil() {
return new ChenGuangPencil();
}
@Override
public Eraser createEraser() {
return new ChenGuangEraser();
}
}
// 真彩工厂
public class TrueColorFactory implements AbstractFactory{
@Override
public Pencil createPencil() {
return new TrueColorPencil();
}
@Override
public Eraser createEraser() {
return new TrueColorEraser();
}
}
抽象产品角色(Pencil.java、Eraser.java)
// 铅笔
public interface Pencil {
public void draw();
}
// 橡皮
public interface Eraser {
public void erase();
}
具体产品角色(ChenGuangPencil.java、TrueColorPencil.java、ChenGuangEraser.java、TrueColorEraser.java)
// 晨光铅笔
public class ChenGuangPencil implements Pencil {
@Override
public void draw() {
System.out.println("用晨光铅笔画图。");
}
}
// 真彩铅笔
public class TrueColorPencil implements Pencil {
@Override
public void draw() {
System.out.println("用真彩铅笔画图。");
}
}
// 晨光橡皮
public class ChenGuangEraser implements Eraser {
@Override
public void erase() {
System.out.println("用晨光橡皮擦除晨光铅笔画的图。");
}
}
// 真彩橡皮
public class TrueColorEraser implements Eraser {
@Override
public void erase() {
System.out.println("用真彩橡皮擦除真彩铅笔画的图。");
}
}
测试类(AbstractFactoryTest.java)
public class AbstractFactoryTest {
public static void main(String[] args) {
// 1、晨光
AbstractFactory factory = new ChenGuangFactory();
Pencil pencil = factory.createPencil();
pencil.draw(); // 用晨光铅笔画图。
Eraser eraser = factory.createEraser();
eraser.erase(); // 用晨光橡皮擦除晨光铅笔画的图。
// 2、真彩
AbstractFactory factoryT = new TrueColorFactory();
Pencil pencilT = factoryT.createPencil();
pencilT.draw(); // 用真彩铅笔画图。
Eraser eraserT = factoryT.createEraser();
eraserT.erase(); // 用真彩橡皮擦除真彩铅笔画的图。
}
}
测试结果:
优点
1、拥有简单工厂模式、工厂方法模式一样的优点:客户端不需要知道对象被创建的细节
2、当产品族中多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的产品。
3、增加产品族,符合开闭原则。
缺点
1、增加产品等级结构时,不符合开闭原则。
总结
抽象工厂模式在工厂方法模式的基础上,增添了产品族
和产品等级结构
的概念,以及只使用同一个产品族中的约束,使得抽象工厂模式符合现实生活中的某些场景,成为实用的设计模式,再加上抽象工厂模式实现高内聚低耦合,也为其广泛应用提供基础。
完
(给晨光和真彩做广告,是不是应该收点广告费???)
参考:
2018年8月25日18:31:58
由于博主水平有限,如果本文有什么错漏,请不吝赐教
感谢阅读,如果您觉得本文对你有帮助的话,可以点个推荐
posted on 2018-08-25 18:38 mingmingcome 阅读(666) 评论(0) 编辑 收藏 举报