最近在看《Head First 设计模式》,学到了一些模式,在这里写些我个人感觉比较适配的例子
1.策略模式
策略模式在游戏中的开发还是挺常见的,比如植物大战僵尸中的向日葵和太阳花,
两者的不同点就是 产出的东西不同。一个是太阳,另一个是金币 或银币。
书中是以一个 鸭子 的例子入手。比如我要设计一个模拟鸭子 软件
先抽象出一个类吧
#ifndef __Duck_H__
#define __Duck_H__
class Duck
{
public:
virtual void quack();//会呱呱叫
virtual void swim();//会游泳
virtual void display();//类似于绘图,目前仅仅是输出到控制台
};
#endif
其他子类继承这个类就可以了
//绿头鸭子
class MallardDuck:public Duck
{
public:
void display()
{
//外观是绿头
}
};
//红头鸭子
class RedheadDuck:public Duck
{
public:
void display()
{
//外观是红头
}
};
但如果要加上会飞这个行为 又该怎么办?
简单,在超类加上fly()方法 。修改后的Duck
class Duck
{
public:
virtual void quack();//会呱呱叫
virtual void swim();//会游泳
virtual void display();//类似于绘图,目前仅仅是输出到控制台
virtual void fly();//会飞
};
好吧,问题来了,如果有 橡皮鸭又该怎么办,无生命会飞的东西(僵尸?飞僵?)
接着用继承,覆盖了fly()方法,让它什么都不做
//橡皮鸭
class RubberDuck:public Duck
{
public:
virtual void fly()
{
//只是覆盖,什么事都不做
}
};
问题解决了,本节结束。。。。。才怪。
如果要求加入一个木头鸭子(不会叫也不会飞)。按照思路的话我需要覆盖quack()和fly()方法。这样下去无休无止。。。
单纯地这样改变会有几点不好:
1.代码在多个子类中重复
2.很难知道鸭子得全部行为
3.运行时得行为不易改变
4.改变会牵一发而动全身,造成其他鸭子不想要得改变
那么利用接口会如何?
抽象出一个Flyable接口,只有会飞得鸭子才实现此接口。同样,Quackable接口对应会叫的鸭子。
说干就干。看代码
class Duck
{
public:
virtual void swim();//会游泳
virtual void display();//类似于绘图,目前仅仅是输出到控制台
};
//----------------------------------Flyable------------------------------
class Flyable
{
public:
~Flyable(){}
virtual void fly()=0;
};
//----------------------------------Quackable-------------------------------
class Quackable
{
public:
~Quackable(){}
virtual void quack()=0;
};
//绿头鸭子
class MallardDuck:public Duck,public Quackable,public Flyable
{
public:
void display()
{
//外观是绿头
}
virtual void fly();
virtual void quack();
};
//红头鸭子
class RedheadDuck:public Duck,public Quackable,public Flyable
{
public:
void display()
{
//外观是红头
}
virtual void fly();
virtual void quack();
};
//橡皮鸭
class RubberDuck:public Duck
{
public:
virtual void fly()
{
//只是覆盖,什么事都不做
}
};
接口一开始似乎不错,解决了问题,但(c++,java)接口不具有实现代码,所以继承无法达到代码复用
解决:
接下来要用到策略模式了。针对接口编程,而不是针对实现编程
利用接口代表每个行为,而行为得每个实现都将实现其中得一个接口。所以这次鸭子类不会负责实现Fly和Quack,反而是由我们制造一组其他类专门实现FlyBehavior和QuackBehavior “行为”,由行为类而不是Duck类实现行为接口
先看行为类的实现
飞行类
#ifndef __FlyBehavior_H__
#define __FlyBehavior_H__
#include<iostream>
using namespace std;
class FlyBehavior
{
public:
virtual ~FlyBehavior(){}
virtual void fly()=0;
};
//---------------------------FlyWithWings--------------------------------------------------
class FlyWithWings:public FlyBehavior
{
public:
virtual void fly()
{
cout<<"我在用翅膀飞行"<<endl;
}
};
//------------------------FlyNoWay-----------------------------------------------------
class FlyNoWay:public FlyBehavior
{
public:
virtual void fly()
{
cout<<"我不会飞"<<endl;
}
};
//--------------------------FlyRocketPowered-------------------------------------------------------------
class FlyRocketPowered:public FlyBehavior
{
public:
virtual void fly()
{
cout<<"我正在用火箭飞"<<endl;
}
};
#endif
#ifndef __QuackBehavior_H__
#define __QuackBehavior_H__
#include<iostream>
using namespace std;
class QuackBehavior
{
public:
virtual ~QuackBehavior(){}
virtual void quack()=0;
};
//-----------------------Quack-----------------------------------------------
class Quack:public QuackBehavior
{
public:
virtual void quack()
{
cout<<"呱呱叫"<<endl;
}
};
//------------------------Squeak-----------------------------------------------
class Squeak:public QuackBehavior
{
public:
virtual void quack()
{
cout<<"吱吱叫"<<endl;
}
};
//---------------------------MuteQuack-----------------------------------------------------
class MuteQuack:public QuackBehavior
{
public:
virtual void quack()
{
//什么也不做,不会叫
}
};
#endif
看看新的鸭子类
//Duck.h
#ifndef __Duck_H__
#define __Duck_H__
#include<iostream>
using namespace std;
class QuackBehavior;
class FlyBehavior;
class Duck
{
private:
FlyBehavior*flyBehavior;
QuackBehavior*quackBehavior;
public:
Duck();
~Duck();
virtual void swim();//会游泳
virtual void display();//类似于绘图,目前仅仅是输出到控制台
void performFly();
void performQuack();
void setFlyBehavior(FlyBehavior*behavior);
void setQuackBehavior(QuackBehavior*behavior);
};
//绿头鸭子
class MallardDuck:public Duck
{
public:
virtual void display()
{
cout<<"绿头鸭子"<<endl;
}
};
//红头鸭子
class RedheadDuck:public Duck
{
public:
void display()
{
cout<<"红头鸭子"<<endl;
}
};
//橡皮鸭
class RubberDuck:public Duck
{
public:
void display()
{
cout<<"橡皮鸭子"<<endl;
}
};
#endif
//Duck.cpp
#include "Duck.h"
#include "FlyBehavior.h"
#include "QuackBehavior.h"
Duck::Duck()
:flyBehavior(nullptr),quackBehavior(nullptr)
{
}
Duck::~Duck()
{
}
void Duck::swim()
{
cout<<"我正在游泳"<<endl;
}
void Duck::display()
{
}
void Duck::performFly()
{
flyBehavior->fly();
}
void Duck::performQuack()
{
quackBehavior->quack();
}
void Duck::setFlyBehavior(FlyBehavior*behavior)
{
flyBehavior = behavior;
}
void Duck::setQuackBehavior(QuackBehavior*behavior)
{
quackBehavior = behavior;
}
再看看main.cpp
#include<iostream>
#include<conio.h>
#include "Duck.h"
#include "FlyBehavior.h"
#include "QuackBehavior.h"
int main()
{
//绿头鸭子
Duck*duck = new MallardDuck();
duck->setFlyBehavior(new FlyWithWings());
duck->setQuackBehavior(new Quack());
duck->display();
duck->performFly();
duck->performQuack();
//橡皮鸭
Duck*duck2 = new RubberDuck();
duck2->setFlyBehavior(new FlyNoWay());
duck2->setQuackBehavior(new MuteQuack());
duck2->display();
duck2->performFly();
duck2->performQuack();
duck2->setFlyBehavior(new FlyRocketPowered());
duck2->performFly();
//不至于直接退出
_getch();
return 0;
}
测试一下