设计模式之策略模式

 策略模式的理解

  • 最初的设计

假设有一家公司——帕特兰,该公司研制了一款生产设备,可以生产出多功能高科技产品uranus G1(第一代)。G1产品具有AB两项功能,深受全球用户喜爱,掀起一股抢购浪潮,产品开始大规模销往世界各地,中国、意大利、法国、德国等很多国家。

但是很快,各国用户开始反映,虽然AB功能非常实用,但产品外观有些单一,销往各国的产品长得都一样,如果每款产品可以体现各国自己的风情文化,岂不更好?

帕特兰公司立刻采取行动,针对各国风情设计了不同的外观,如销往中国的加入了中国风,销往法国的则加入了浪漫的元素。于是,生产线现在是这样:

wKiom1Ohp6HDSWcpAACS6KjjdtE731.jpg


图1

  • 加入新的功能

随着用户的需求不断增加,帕特兰公司决定给G1系列产品加入功能C。因为生产线采用了OO的思想,只需要在基类中加入功能C(如图2所示),那么所有继承该基类的子类(即图1中标号为234的分支线)生产出的G1产品,自然就具有了功能C,设计者们这下尝到了OO设计与继承的甜头。


wKioL1Ohp4bCjrTAAABxU7pGRg0930.jpg

图2

  • 产品又升级

现在又需要加入D功能。帕特兰公司在这方面已经驾轻就熟,只需要像加入C功能一样在基类中加入D就好了,而且产品开始销往更多的国家。

wKiom1Ohp9OD56FAAACLXQGkunQ400.jpg

图3

可是这次没有像之前那么顺利,由于各国地区文化差异,法国和美国某些地区的用户,美国加州的用户不喜欢D功能,法国巴黎的用户觉得D功能稍微修改一下,变成D1功能比较合口味。帕特兰公司的设计者采用了这样的方式解决这个问题:生产线再加入一级过滤层,

对个别地区的产品进行修整,其余大部分产品保持原样即可。


wKiom1OhqBCzSQR_AACzqRnIpp8395.jpg

图4

虽然解决了这个问题,但是帕特兰公司的设计者开始发现设计中存在一个非常大的问题,那就是以后还会加入E功能,还会销往更多的国家和地区,如果E功能在更多地区出现D的类似情况,可就不妙了,比如,日本东京的用户觉得E改成E1,而中国杭州的用户偏偏喜欢E,意大利罗马的用户觉得改成E2更舒服。你想象一下,随着功能的不断加入,销售地区更多,地区文化差异大,在图中的2级分支处,让一个人来维护,那工作量将是多么的惊人!

  • 策略模式怎么做

帕特兰公司的设计人员开始研究策略模式,发现原来有一种更好的设计方式,可以将刚才那个噩梦般的维护工作瞬间变得容易了。

设计人员做了以下几件事情:

  1. 将世界通用的功能ABC保留在基类中实现,因为这些功能满足所有地区,几乎不会变动;

  2. 将容易随着地区不同而变动的DE功能的实现从基类中抽离出来,只留了两个位置de,表示这两个功能,主生产线暂时不实现;

  3. 对位置de规定了接口规范,比如d位置有三个菱形插孔,e位置有两个圆形插孔,采用该接口规范设计的零件可以安插在相应的位置,即插即用

  4. 成立一条独立的生产线line2(原来的生产线统称为line1),专门负责生产实现DD1、空DEE1、空E等功能的零件,并采用3中规定的接口标准。

  5. 安排一个人peter,专门负责从line1中取出G1半成品(即只有ABC功能,DE只留了位置),从line2取出生产出的DE零件,将零件安插在相应的位置上;

现在情况是什么呢?

  1. 以后再有哪个地区突然说不喜欢DE,或者要改成D2E2,亦或是D3E3也没关系,只需要在line2中添加一个这样的零件,而line1仍旧像以前一样保留de位置,一点修改都不用做,在打算生产具有D2E2D3E3功能的产品时,peter自然会取出新添加的零件,安插在预留的位置,对于peter而言,拿的动作和安插的动作也是完全相同,只是拿了不同的零件而已。

这就是策略模式。

  • 再来看概念

现在来看一下策略模式的抽象概念,如果你看懂了前面的例子,那么请原谅我到这里才介绍概念。

策略模式的概念:将一系列行为(动作、算法)封装起来,功能类似的行为都实现一个统一的接口,使这些行为的变化修改独立于行为的使用者。

这里的行为对应的就是line2生产的具有功能D2D3E2E3的零件;

统一的接口就是预留的位置de所规定的一系列特征,如三插孔、菱形等;

行为的使用者即line1生产出的半成品;

预留位置,其实就是在基类中加入一个行为对象,以接口类型来引用(即使用组合,针对接口编程),委托给变量来实现具体功能;

安插零件的动作则对应基类的set方法,来设置实际的行为对象;

Peter扮演的就是基类和行为类的用户(可以理解成写main函数的程序员),针对不同的地区调用set方法设置不同的行为对象。

  • 设计原则

  1. 多用组合少用继承

  2. 针对接口编程,而非针对实现编程

  3. 分离并封装易于变化的行为,独立于固定不变的部分

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章