本文共 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,解除分支判断带来的有些。若有理解错误,感谢指出!