博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式<六>抽象工厂模式
阅读量:2401 次
发布时间:2019-05-10

本文共 3416 字,大约阅读时间需要 11 分钟。

抽象工厂模式的基本概念

提供一个创建一系列相关或依赖对象的接口,而无需指定他们具体的类。

了解抽象工厂模式就需要先了解产品族以及产品等级结构的概念。
在抽象工厂模式中,一个具体工厂生产一个产品族,产品族即各种不同的产品的组合,例如正方形,圆形,椭圆形都是不同的,又有共同的抽象→形状。
例如加减乘除的算法都是不同的,又有共同的抽象→计算。
这些都是一个个的产品族,产品等级结构即一个具体产品的不同表现,如形状的颜色,大小。算法的参与运算个数。

一般情况下,

多少个产品等级结构,多少个工厂方法。
多少个产品族,多少个具体工厂。
以下是一张我引用的图:
这里写图片描述
引入与工厂模式相似的简单思想图:
这里写图片描述
和简单工厂模式于工厂方法模式比较,很容易看出
抽象程度上简单工厂模式<工厂方法<抽象工厂模式。
简单工厂模式:一个具体工厂生产多个具体产品。一个抽象产品。
工厂方法模式:一个具体工厂生产一个具体产品。多个抽象产品。
抽象工厂模式:一个具体工厂生产多个具体产品。多个抽象产品。
简单工厂模式与工厂方法模式见:

什么时候用抽象工厂模式

如果产品少而且基本不变动,用简单工厂模式。

如果产品单一,用工厂方法模式。
如果产品丰富,用抽象工厂模式。
同时,使用以上的几种模式都封装了对象创建的具体细节,使客户不用关注对象是如何来的,更关注于取得了对象。
抽象工厂模式再优化了工厂方法模式的细节上,因有了产品族的概念,在产品的生产上也会多出比工厂方法模式更多的类,这也是抽象带来的缺点。所以再实际开发中,一定要思考好该使用怎样的模式,或者说怎样的更简单的模式可以更好的胜任。考虑的不仅仅是可以怎么用,而是什么更适合用。

抽象工厂模式怎么用

我们根据之前的思想图,

一个抽象工厂模式需要有一个抽象的工厂,多个抽象的产品。
一个具体的工厂生产多个具体的产品。
以加减乘除为例:
需要一个两数的算法工厂能生产两数加法,两数乘法。
一个三数的算法工厂能生产三数加法,三数乘法。
那么,加法与乘法构成了一个产品族。
两数与三数构成了一个产品等级结构。

首先,我们需要一个两数产品的共同抽象:

/** * @author : cjd * @Description :抽象加法产品 * @create : 2018-01-03 10:19 **/public interface AddCalc {
int getResult(int a, int b);}

以及实现该抽象的具体产品:

/** * @author : cjd * @Description :两数具体加法产品 * @create : 2018-01-03 10:36 **/class TwoNumberAdd implements TwoNumberCalc {    @Override    public int getResult(int a, int b) {        return a + b;    }}/** * @author : cjd * @Description :两数具体乘法产品 * @create : 2018-01-03 10:36 **/class TwoNumberMultiply implements TwoNumberCalc {    @Override    public int getResult(int a, int b) {        return a * b;    }}

同理得三数抽象产品与具体产品。

再根据其产品含有的产品等级结构(两数、三数)创建抽象的工厂:

/** * @author : cjd * @Description :抽象算法工厂 * @create : 2018-01-03 10:41 **/public interface CalcFactory {
TwoNumberCalc createTwo(); ThreeNumberCalc createThree();}

及具体的产品工厂:

/** * @author : cjd * @Description :具体加法工厂 * @create : 2018-01-03 10:48 **/class AddFactory implements CalcFactory {    @Override    public TwoNumberCalc createTwo() {        return new TwoNumberAdd();    }    @Override    public ThreeNumberCalc createThree() {        return new ThreeNumberAdd();    }}/** * @author : cjd * @Description :具体乘法工厂 * @create : 2018-01-03 10:51 **/class MultiplyFactory implements CalcFactory {    @Override    public TwoNumberCalc createTwo() {        return new TwoNumberMultiply();    }    @Override    public ThreeNumberCalc createThree() {        return new ThreeNumberMultiply();    }}

客户端进行如下调用:

/** * @author : cjd * @Description : * @create : 2018-01-03 10:52 **/public class Main {
public static void main(String[] args) { CalcFactory calcFactory; //加法工厂 calcFactory = new AddFactory(); TwoNumberCalc twoAdd = calcFactory.createTwo(); ThreeNumberCalc threeAdd = calcFactory.createThree(); //乘法工厂 calcFactory = new MultiplyFactory(); TwoNumberCalc twoMultiply = calcFactory.createTwo(); ThreeNumberCalc threeMultiply = calcFactory.createThree(); System.out.println(twoAdd.getResult(1, 2) + " " + threeAdd.getResult(1, 2, 3)); System.out.println(twoMultiply.getResult(1, 2) + " " + threeMultiply.getResult(1, 2, 3)); }}

如此,暴露出工厂便实现对产品的解耦,其缺点也显而易见,

放出最后的图自己体会:
这里写图片描述
记此,只为了提醒,慎用设计模式。

后记

对设计模式的学习我是参造着《大话设计模式》与网络资料的。

在《大话设计模式》里对抽象工厂模式有这样的几种优化处理:
1.通过简单工厂模式将繁琐的(抽象工厂+具体工厂A+具体工厂B)简化成一个具体工厂,在其中通过switch或if…else生成具体的产品,这样的做法能解除客户端对具体工厂的依赖。避免了一处改,处处改。
2.当产品族比较多且繁琐,大量的if…else就显得臃肿,此时可通过反射创建来避免大量的使用判断。
3.使用反射也不可避免会导致需要修改工厂时要修改程序的代码,所以通过配置文件来优化导入。
《大话设计模式》中并提供了这样的一种思想:
所有在用简单工厂模式的地方,都可以考虑使用反射技术来取出switch或if,解除分支判断带来的有些。

若有理解错误,感谢指出!

你可能感兴趣的文章
姜疯子
查看>>
seb小铺
查看>>
Madaha--RHCE
查看>>
我的派派播客(视、音频)*
查看>>
PGL系统管理部BLOG
查看>>
我的博客*
查看>>
我的BOKEE网*
查看>>
处理器架构划分
查看>>
我的波普播客
查看>>
内存的SDR与DDR的区别
查看>>
我的新浪博客*
查看>>
服务器技术概述
查看>>
前端总线
查看>>
ora-600's blog
查看>>
服务器内存技术
查看>>
什么是超线程技术?
查看>>
北桥芯片
查看>>
CPU主频
查看>>
南桥芯片
查看>>
CPU外频
查看>>