策略模式(Strategy Pattern)

来源:互联网 发布:淘宝众筹首页 编辑:程序博客网 时间:2024/06/06 04:56

1、传统程序设计思考

     面向对象的编程方法中“继承”是一个重要的特性,在面向对象的编程中经常使用。通过使用继承可以提高代码的复用、提高开发的效率。大大提高了程序的维护和功能扩充的遍历性。
按照“继承”和“封装”的原则我们通常这样设计程序,如下图:


    设计一个基类Animal类,提取了共同的特性抽象了Animal的两个行为:Sound和Move。派生出Dog、Cat、GraySwan类,根据不同的动物行为的不同都“重写”了makeSound和makeMove方法。
    仔细思考这种模式还是存在一些问题:疑问

       (1)派生的类多时,每个派生类都“重写”基类的方法,也会出现代码的重复
    (2)行为在基类或派生类中实现,行为的具体“实现”与类绑定,没办法改变。在不同的时期,行为可能或发生改变


2、程序设计的优化

   (1) 程序的设计第一个原则:把应用中可能需要改变之处,独立出来,不要和那些不需要变化的代码混合在一起
    我们把上面的类设计进行一下划分:


为了要把动物的两个行为从Animal的类中提取出来,建立一个组新类来代表每个行为。
(2)程序设计的第二个原则:针对接口编程,而不是针对实现编程。
在对象的不同时期,行为可能也会发生变化,原本的方法类与行为实现绑定,使得行为不能改变。我们可以把Animal类中的行为设定为一个接口,可以在“运行时”动态的“改变”Animal的行为。也就是针对接口编程,而不是针对实现编程。


1) Animal类中makeSound函数实现:
void Animal::makeSound(){    soundBehavior->makeSound();}

在动物进行叫的时候,Animal对象只需要调用soundBehavior对象的makeSound即可,叫这个行为由对象soundBehvior对象代理
2) Animal类中setSound函数实现:
void Animal::setSound(SoundBehavior sound){    soundBehavior = sound;}

此函数提供了设置叫这个行为的具体实现,在运行时,可以通过这个接口修改对象的行为
3) 派生类中构造函数的实现:
void Dog::Dog(){    setSound(new wwSound); }

在派生类的构造函数中初始化具体行为实现,在运行时可以通过setSound方法修改具体的行为

按照这个方案进行修改设计,将容易改变的行为进行独立封装,采用面向对象的“多态”特性,通过接口实现对象具体行为的绑定,这样程序设计的优点:
  • 降低了代码的耦合性
  • 动物的行为便于扩展。增加行为的派生类实现具体行为即可
  • 动物的行为在程序运行时可以动态的改变
对比传统的程序设计方式,及保持了面向对象的“封装”“继承”“多态”的特性,也解决了上面存在的问题。

(3)、程序设计的第三个原则:多用组合、少用继承
"有一个"可能比“是一个”更好。“有一个”关系相当有趣:每一个鸭子都有一个FlyBehavior和一个QuackBehavior,好将飞行和呱呱叫委托给他们代为处理。当你将两个类组合起来使用,这就是“组合”。这种做法和“继承”不同的地方在于,鸭子的行为不是继承来的,而是和适当的行为对象“组合”来的。使用组合建立系统具有很大的弹性,不仅可将算法族封装成类,更可以“在运行时动态的改变行为”,只要组合的行为对象符合正确的接口标准即可

3、策略模式(Strategy Pattern)

策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立与使用算法的客户



原创粉丝点击