简单工厂与策略模式的结合
下面我门通过一个厂商收银软件的编码学习一下简单工厂与策略模式相结合的应用。
场景:做个商场收银软件,营业员根据所购买的商品的单价和数量,向客户收费,计费方式分为三种:正常收费、打8折、满300返100。
(1)商场促销的简单工厂
根据面向对象的编程思想——抽象,分析得出:正常收费、打几折、满***返***的收费方式,基本都是一样的,只是有个 初始化的参数加以区别就可以了,所以此软件共抽象出如下几个类:
CashSuper:现金收费抽象类。
CashNormal:正常收费子类
CashRebate:打折收费子类
CashReturn:返利收费子类。
CashFactory:现金收费工厂类。
下面我们看一下简单工厂实现的代码结构图:
简单工厂模式虽然也可以解决这个问题,但这个模式只是解决对象的创建问题,而且由于工厂本身包含了所有的收费方式,商场可以经常性地更改打折额度和返利额度,每次维护或扩展收费方式都要改变这个工厂,以致代码需要重新编译部署,这是非常糟糕的,所以用它不是最好的办法。面对算法的时常变动,应该有更好的办法。
下面我们用策略模式来改进工厂模式的不足。
(2)商场促销的策略模式:
策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替代,此模式让算法的变化,不会影响到使用算法的用户。
下面我们看一下策略模式实现的代码结构图:
CashSuper:抽象策略,定义所有支持算法的公共接口。
CashNormal、CashRebate、CashReturn是三个具体的策略,也就是策略模式中的具体算法,继承于CashSuper。
CashContext,用一个具体的收费方式类配置,维护对一个策略对象(CashSuper)的引用。通过构造方法,传入具体的收费策略。
策略模式的缺点:在客户端判断用哪一个算法。而用简单工厂是可以将判断的过程从客户端程序移动的。
(3)简单工厂与策略模式的CashContext结合。
代码的结构图:
注意:CashContext类的构造方法的参数不是具体的收费策略对象,而是一个字符串,表示收费的类型。这样就将程序的判断从客户端移出。
总结:商场收银系统的计费方式,无论是打折还是返利,其实都是一些算法,用工厂来生产算法对象,这是没错的,但算法本身只是一种策略,最重要的是这些算法随时都可能互相替换的,这就是变化点,而封装变化点是面向对象的一种重要的思维方式。鉴于每个模式都有其优缺点,所以有些情况我们将其几个设计模式结合起来用,各取其优点,避其缺点,达到程序设计的最优化。