• 设计模式 策略模式


        设计模式,我对它的理解就是,解决问题的方法,模式本身的重要性自不必说,但是我认为模式之外的解决问题的方法才是我们真正需要掌握的,

                       其中,最基本的三点:封装变化,模块化,模块间的低耦合 

        以前也看过Head first 设计模式,但总有点雾里看花的感觉,总觉得不是那么的真切。不过一些思想已经印在脑子里了,这半年来体会良多,于是决定再把这本书看一遍,温故而知新。

        对于软件开发而言,一个很让人头疼的一个拦路猛虎就是“变”,可能是客户有了新的需求,可能是我们要使用新的技术,也可能是我们本领提高了,想要来重构原来的软件……

        设计模式很大程度上也是为了解决“变”的问题,当有变化产生的时候,如何使我们的代码改动最少,如何做到模块的独立性,使模块间的影响最小(也就是松耦合), 关于变化的一个设计原则是:

    设计原则找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要发生变化的代码放在一起。

     我们来看一看,这个原则是怎么应用在鸭子问题上的:

    1. 鸭子会 叫(quack),游泳(swim),...(未知的行为,会引起变化的部分

    2. 有多种鸭子:绿头鸭(MallardDuck),红头鸭(RedheadDuck),模型鸭....(未知种类的鸭子,会引起变化的部分) 

    3. 鸭子可能会有更多的行为,不同鸭子的行为也不同

    如果这是一道分析设计题目,我很容易就会想到继承,分析如下:

    我的方案1: 

        1. 将鸭子(Duck)类设计为抽象类,在其中实现我以为通用的行为,如swim,这样可以使得子类就可以重用父类的代码,如何做到代码重用也是一个问题呢

        2. 鸭子类的子类,包括MallardDuck啊,RedheadDuck啊什么的,在这些类中重写那些他们独有的行为。

     下面来看看这个方案的问题吧

     首先,继承有一个问题:父类中所作的任何修改都会反应到子类中,

             比如,我在父类中增加了一个fly方法,那么所有的子类都会继承这个方法,

             如果有的鸭子不会飞,我就要在子类中重写这个方法,从而父类的变化牵动了子类一块变化(而这正是我们想要解决的问题)

             可能你会说,这是需求不明确造成的,呃~,需求真的能明确么?

     其次,如果某几个子类的某种行为相同,这就会造成代码重复,当然了,你可能会采取某种方法来消除这种重复,例如,将这段重复的代码封装到一个函数中。

     再次,你能想象这样的设计如何实现运行时动态改变鸭子的行为么? 


    怎样找出解决方法? 

         这个时候就是我们学以致用的时候了,根据设计原则,"找出应用中可能需要变化之处,把他们独立出来"。

    设计原则针对接口编程,而不是针对实现编程。

     这条设计原则比较抽象,不易理解,但是想让我们来看下我们的鸭子类,

     鸭子类中实现了quack(),swim()这些我们自以为通用的行为,这就造成鸭子超类依赖于具体的实现。

     而我们想要的是:鸭子类不需要关心实现的细节。 

     既然我们的标题是策略模式,那么就让我们看看策略模式,以及策略模式如何解决这个问题。

    策略模式定义算法族,并将它们封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

     这里所说的算法是一个泛泛的概念,它想表达的含义是将相同类型的行为视为一个算法族,如swim,quack等

      冒泡排序,希尔排序,快速排序,这可以被定义为一个算法族,

      同样的,对应于我们的鸭子,

      swim也可以被定义为一个算法族,蝶泳,狗爬式,等等, 

     以此类推,我们可以将swim, quack,fly这三种行为提取出来,封装为三个接口,简单的实现如下:

      1 // Fly行为接口

     2 class FlyBehavior{
     3 public:
     4     virtual void fly() = 0;
     5     virtual ~FlyBehavior(){};
     6 };
     7 
     8 class Duck{
     9 public:
    10     // 添加此方法以支持运行时动态修改 fly行为
    11     void setFlyBehavior(shared_ptr<FlyBehavior> fb){
    12         flyBehavior = fb
    13     }
    14 
    15     // 我们的fly
    16     void fly(){ 
    17         flyBehavior->fly() ;
    18     }
    19 
    20 private:
    21     // 使用组合的方式
    22     shared_ptr<FlyBehavior> flyBehavior;
    23 };

     上边的代码只是简单地实现了鸭子类 和 FlyBehavior ,不过雏形确已初具,

     Duck的子类只需要使用正确的行为类就可以了。

     而父类接口的变化,对子类的影响也很小;

     如果代码中的鸭子类增加了新的行为,如swim(),那么,子类只需要调用setSwimBehavior()设置正确的Swim行为就可以了,而子类的实现不必发生变化

     更好地方式是,我们采用工厂方法,将创建鸭子的行为封装在工厂方法中

  • 相关阅读:
    层的问题,
    创建一个函数,返回元素个数为n的int型数组中的最小值
    c语言中编写函数求五个学生中的最高分
    c语言中没有形参的函数(例题:逆向输出正整数)
    创建一个函数,对元素个数为n的int型数组进行倒序排列。
    c语言 函数中数组的传递, 形参和实参。
    c语言中函数的传递和const类型的修饰符
    c语言中的文件作用域、函数原型声明、定义声明和非定义声明
    c语言中文件包含指令和头文件
    c语言中数组元素的线性查找
  • 原文地址:https://www.cnblogs.com/hdtianfu/p/2747207.html
Copyright © 2020-2023  润新知