[例子向]简单说一下设计模式

来源:互联网 发布:年会策划 知乎 编辑:程序博客网 时间:2024/04/27 07:33

最近在看《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;}

测试一下



0 0