第二章 场景模式

1. 设计原型 - a Duck

在这里插入图片描述

说明:

  1. 我们假设所有的Duck叫声都一样,quack~~,游泳的姿态也相同~~

  2. 每种Duck的外型特征彼此不同 ~~

  3. 图示中斜体文字表示, 函数被virtual xxx = 0 关键字所声明,为抽象接口。对应的代码如下,以后不再追加代码。

    #include <iostream>
    
    using namespace std;
    
    class Duck
    {
        public:
        
    	virtual void quack(void)
    	{
    		cout << "all Ducks quack" << endl;
    	}
    	virtual void swim(void)
    	{
    		cout << "all Ducks swim" << endl;
    	}
    	virtual void display(void) = 0;
    };
    
    class MallardDuck : public Duck
    {
        public:
        
        void display (void)
        {
            cout << "A MallardDuck display" << endl;
        }
    };
    
    class RedheadDuck  : public Duck
    {
        public:
        void display (void)
        {
            cout << "A RedheadDuck display" << endl;
        }
    };
    
    int main()
    {
        MallardDuck  aMallardDuck;
        RedheadDuck  aRedheadDuck;
        
        aRedheadDuck.quack();
        aMallardDuck.quack();
        
        aRedheadDuck.display();
        aMallardDuck.display();
        return 0;
    }
    
    ————————————————————————打印输出———————————————
    all Ducks quack
    all Ducks quack
    A RedheadDuck display
    A MallardDuck display
    

2. 设计原型的改进-飞行能力

**需求:**我们需要为Duck 添加飞行功能的支持

方案: 基类Duck中添加fly接口,这样所有子类都具备了fly的能力

virtual void Ducks::fly(void)
{
	cout << "all Ducks fly" << endl;
}

**问题:**考虑橡胶制成的小鸭子,它应该具有飞行能力吗?
橡胶Duck不具备飞行能力,所以这个设计有问题

在这里插入图片描述

3. 小节2 提出的问题的修改提案

方案1:
virtual void Ducks::fly(void); 可以在RubberDuck中override 此函数,什么也不做即可

问题:
与方案1类似,RedheadDuck,MallardDuck 叫声和游泳姿态各不相同,因此有必要overrid Duck中的quack 和 swim函数

方案1的改进方案2

void RubberDuck::fly()
{
	cout << "RubberDuck does not fly" << endl;
}
...
void RedhatDuck::swim()
{
	cout << "swim like a RedhatDuck" << endl;
}
void RedhatDuck::quack()
{
	cout << "quack like a RedhatDuck" << endl;
}
...
void MallardDuck::swim()
{
	cout << "swim like a MallardDuck" << endl;
}
void MallardDuck::swim()
{
	cout << "quack like a MallardDuck" << endl;
}

在这里插入图片描述

改进方案2的问题

如果我们有100种Duck呢? 如果以后需要添加类似likefly的功能函数,,但为了避免bug, 在子类中需要重写100次如下的函数。
尽管likefly函数毫无用处。

void RubberDuck::likefly()
{
	cout << "RubberDuck does not fly" << endl;
}

不如,考虑重构?

4. 设计原型的重构

说明:

  • Duck 是一个抽象概念,具有飞行行为,游泳行为,叫声行为。 对于Duck来说,行为不再表现为函数,而是对象 FlyBehavior …
    优点:

  • 代码复用性强。RedHeadDuck 和 MallardDuck 可以复用一个FlywithWings 类

    代码:

    /******************************************************************************
    
                                  Online C++ Compiler.
                   Code, Compile, Run and Debug C++ program online.
    Write your code in this editor and press "Run" button to compile and execute it.
    
    *******************************************************************************/
    #include <iostream>
    
    using namespace std;
    
    class SwimBehavior
    {
        public:
        virtual void swim(void) = 0;
    };
    
    class QuackBehavior
    {
        public:
       virtual void quack(void) = 0;
    };
    
    class FlyBehavior
    {
      public:
      virtual void fly(void) = 0;  
    };
    
    class SwimCircle : public SwimBehavior
    {
        public:
        void swim (void)
        {
            cout << "swim in a circle" << endl;
        }
    };
    
    class SwimLine : public SwimBehavior
    {
        public:
        void swim(void)
        {
            cout << "swim in a line" << endl;
        }
    };
    
    class MuteQuack: public QuackBehavior
    {
        public:
        void quack(void)
        {
            cout << "quack in mute way" << endl; 
        }
    };
    
    class Squeak: public QuackBehavior
    {
        public:
        void quack(void)
        {
            cout << "quack in Squeak way" << endl; 
        }
    };
    
    class FlyNoWay : public FlyBehavior
    {
        public:
        void fly(void)
        {
            cout << "fly do nothing" << endl;
        }
    };
    
    class FlywithWings : public FlyBehavior
    {
        public:
        void fly(void)
        {
            cout << "fly with wings" << endl;
        }
    };
    
    
    class Duck
    {
      public:
      void performFly()
      {
          m_flaybehavior->fly();
      }
      
      void performSwim()
      {
          m_quackbehavior->quack();
      }
      
      void performQuack()
      {
          m_swimbehavior->swim();
      }
      
      protected:
      FlyBehavior *m_flaybehavior;
      QuackBehavior *m_quackbehavior;
      SwimBehavior *m_swimbehavior;
    };
    
    class RedHeadDuck: public Duck
    {
        public:
        RedHeadDuck (void)
        {
            m_flaybehavior = new FlywithWings();
            m_swimbehavior = new SwimCircle();
            m_quackbehavior = new Squeak();
        }
    };
    
    class MallardDuck: public Duck
    {
        public:
        MallardDuck (void)
        {
            m_flaybehavior = new FlywithWings();
            m_swimbehavior = new SwimCircle();
            m_quackbehavior = new MuteQuack(); 
        }
    };
    
    int main()
    {
    
        MallardDuck mallarDuck;
        RedHeadDuck redHeadDuck;
        
        mallarDuck.performQuack();
        mallarDuck.performSwim();
        mallarDuck.performFly();
        cout << "--------cut line-------" << endl;
    
        redHeadDuck.performQuack();
        redHeadDuck.performSwim();
        redHeadDuck.performFly();
        
        return 0;
    }
    
    

5. 小节4重构的一个应用

需求: 乘火箭而飞的鸭子

设计
在这里插入图片描述
代码

class FlyOnRocket: public FlyBehavior
{
    public:
    void fly()
    {
        cout << "I am flying on Rockets" << endl;
    }
};

class SuperDuck: public Duck
{
  public:
    SuperDuck (void)
    {
        m_flaybehavior = new FlyOnRocket();
        m_swimbehavior = new SwimCircle();
        m_quackbehavior = new MuteQuack(); 
    }
};

int main()
{

    SuperDuck superduck;
    superduck.performFly();
    return 0;
}

6. 小节4的设计思路为场景模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值