设计模式<六>抽象工厂模式

抽象工厂模式的基本概念

提供一个创建一系列相关或依赖对象的接口,而无需指定他们具体的类。
了解抽象工厂模式就需要先了解产品族以及产品等级结构的概念。
在抽象工厂模式中,一个具体工厂生产一个产品族,产品族即各种不同的产品的组合,例如正方形,圆形,椭圆形都是不同的,又有共同的抽象→形状。
例如加减乘除的算法都是不同的,又有共同的抽象→计算。
这些都是一个个的产品族,产品等级结构即一个具体产品的不同表现,如形状的颜色,大小。算法的参与运算个数。

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

什么时候用抽象工厂模式

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

抽象工厂模式怎么用

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

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

/**
 * @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,解除分支判断带来的有些。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值