现在的位置: 首页 > 综合 > 正文

一、策略者模式(Strategy Pattern)—-3

2012年09月29日 ⁄ 综合 ⁄ 共 1733字 ⁄ 字号 评论关闭

回顾上面的例子:

1、我们使用继承的方法,结果因为鸭子的行为在子类中会不断的变化,为勒适应这种变化,我们不得不一遍遍的在子类中覆盖父类的方法,结果导致勒代码的大量重复。

2、然后,我们使用了接口的方法,结果仍然不行,因为接口实现,无法做到代码的重复利用,这在一个可扩展的程序中,显然是不号的。

3、然后,我们使用了策略者模式,将变化的部分,独立出来,转换为两组策略,fly策略组和quake策略组。然后采用组合的方式,使得同种策略的不同实现可以相互的替换,解决了代码的重复和不可重利用的缺点。

一、策略者模式的定义:

The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.(策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。)


二、策略者模式的设计原则:

1、将变化的部分独立出来,定义一系列变化的实现,并将每一个封装起来,并可以相互替换。

2、针对接口编程,而不是针对实现编程。针对接口编程,并不是侠义上的java的interface,而是“针对超类型”编程。

3、多用组合,少用继承。

Favor composition over inheritance.(优先使用对象组合,而非类继承)

关于组合和继承,我们只要这样来理解即可:组合是一种“HAS-A”关系,而继承是一种“IS-A”关系。很明显“HAS-A”要比“IS-A”更灵活一些。也就是说在创建系统的时候,我们应该优先使用对象组合,因为它不仅可以给你提供更多灵活性和扩展性,而且还使你可以在运行时改变行为(组合不同的对象),这简直是酷毙了!但是也不是说继承就是不能用,只是说应该把继承应用在相对更稳定,几乎没有变化的地方,例如前面的Duck类里的Swim()方法,因为可以肯定所有鸭子一定都会游泳,所以就没有必要给这个行为提供基于Strategy模式的实现方式,因为那样做除了是程序更复杂以外,没有什么意义。

三、应用场景和优缺点:

上面我们已经看过了Strategy模式的详细介绍,下面我们再来简单说说这个模式的优缺点吧!怎么说呢,人无完人,设计模式也不是万能的,每一个模式都有它的使命,也就是说只有在特定的场景下才能发挥其功效。我们要使用好模式,就必须熟知各个模式的应用场景。

对于Strategy模式来说,主要有这些应用场景:

1、  多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。(例如FlyBehaviorQuackBehavior)

2、  需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。(例如FlyBehaviorQuackBehavior的具体实现可任意变化或扩充)

3、  对客户(Duck)隐藏具体策略(算法)的实现细节,彼此完全独立。

 

对于Strategy模式来说,主要有如下优点:

1、  提供了一种替代继承的方法,而且既保持了继承的优点(代码重用)还比继承更灵活(算法独立,可以任意扩展)

2、  避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。

3、  遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。

对于Strategy模式来说,主要有如下缺点:

1、  因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。

四、策略模式组成:

   1、抽象策略角色:策略类,通常由一个接口或者抽象类实现

   2、具体策略角色:包括了相关的算法和行为,可能不止一个具体策略角色

   3、环境角色:持有一个策略类的引用,最终给客户端调用的。

五、策略模式编写的步骤:

                1、对一组算法抽象出一个共同接口,定义这个共同接口

  2、编写策略类,实现这个借口,每个策略类都有其独特的实现

  3、编写环境角色类,类中持有一个对共同接口的引用,对策略对象注入如set方法和get方法或者用构造方法完成赋值

抱歉!评论已关闭.