学习设计模式有很多好处,得啵得啵得……
blog文章权当我学习日记,免得以后找不到,高手请绕行,不要浪费时间。
以下是我今天用C++写的个Duck类,复现了书中用java写的duck类,大同小异:
#include <iostream>
using namespace std;
//飞行行为类
class Flyable
{
public:
virtual void fly()
{
}
};
//每一种动作都是一个类
class FlyWithWings:public Flyable
{
public:
void fly()
{
cout<<"我会飞"<<endl;
}
};
class FlyNoWay: public Flyable
{
public:
void fly()
{
cout<<"我不会飞"<<endl;
}
};
//叫唤行为类
class Quackable
{
public:
virtual void quack()
{
}
};
//每一种叫都是一种类
class QuackGUAGUA: public Quackable
{
public:
void quack()
{
cout<<"我会呱呱叫"<<endl;
}
};
class QuackZHIZHI: public Quackable
{
public:
void quack()
{
cout<<"我会吱吱叫"<<endl;
}
};
//鸭子超类,类的类叫超类?
class Duck
{
public:
Flyable* m_fly;
Quackable* m_quack;
void Swim()
{
cout<<"所有鸭子都会游泳"<<endl;
}
void PerformFly()
{
m_fly->fly();
}
void PerformQuack()
{
m_quack->quack();
}
protected:
virtual void Display()//所有其他类的鸭子颜色都不同,所以用一个虚函数,让子类来实现
{
}
};
//每一种鸭子都是一种类
class DuckGUAGUA: public Duck
{
public:
DuckGUAGUA()
{
m_fly = new FlyWithWings;
m_quack = new QuackGUAGUA;
}
void Display()
{
cout<<"我是黄色呱呱鸭子"<<endl;
}
};
//每一种鸭子都是一种类
class DuckZHIZHI: public Duck
{
public:
DuckZHIZHI()
{
m_fly = new FlyNoWay;
m_quack = new QuackZHIZHI;
}
void Display()
{
cout<<"我是白色吱吱鸭子"<<endl;
}
};
int main()
{
DuckGUAGUA* duckGuaGua = new DuckGUAGUA;
duckGuaGua->Display();
duckGuaGua->Swim();
duckGuaGua->PerformFly();
duckGuaGua->PerformQuack();
cout<<"************************************"<<endl;
DuckZHIZHI* duckZhiZhi = new DuckZHIZHI;
duckZhiZhi->Display();
duckZhiZhi->Swim();
duckZhiZhi->PerformFly();
duckZhiZhi->PerformQuack();
system("pause");
return 0;
}
此种设计模式的关键地方在于"多态"使用,所推崇的原则的是“针对超类型编程”,更明确地说明是“变量的声明类型应该是超类型,通常是一个抽象类或者一个接口,如此,只要是具体实现此超类型的类所产生的对象,都可以指定给这个变量。这也就意味着,声明类时,不用理会以后执行时的真正的类型对象”,在以上代码中具体表现在:
Duck类中声明两个超类:
Flyable* m_fly;
Quackable* m_quack;
而在mian()函数中,具体实现时,直接将Flyable和Quackable类的子类付给了m_fly和m_quack:
DuckGUAGUA* duckGuaGua = new DuckGUAGUA;
实现:
m_fly = new FlyWithWings;
m_quack = new QuackGUAGUA;
DuckZHIZHI* duckZhiZhi = new DuckZHIZHI;
实现:
m_fly = new FlyNoWay;
m_quack = new QuackZHIZHI;
Duck子类的实例化动作不需要在代码中硬编写,而是“在运行时才指定具体实现的对象”。
书中还提到一个例子:
假设有一个抽象类Animal,有两个具体的实现Dog和Cat,继承自Animal。
“针对实现编程”具体:
Dog dog = new Dog;
d.bark();
但是,“针对超类型编程”则是:
Animal animal = new Dog;
animal.makeSound();
这是一个简单多态的例子,它体现了上面所提到的设计原则。
上面提到了“在运行时才指定具体实现的对象”,我们可以再Duck类中指定一个方法,来设置Flyable和Quackable类所指向的对象,已达到动态修改行为的目的,这里我们给呱呱鸭指定另外一个分型动作“摇摆着飞”,修改如下:
1、添加Flyable的子类FlyYaoBai:
class FlyYaoBai: public Flyable
{
public:
void fly()
{
cout<<"摇摆着飞"<<endl;
}
};
2、Duck类中添加方法SetFlyBehavior(Flyable* myFly):
void SetFlyBehavior(Flyable* myFly )
{
m_fly = myFly;
}
3、main函数中添加代码,实现对呱呱鸭飞行动作的改变:
duckGuaGua->SetFlyBehavior(new FlyYaoBai);
duckGuaGua->PerformFly();
最后运行结果是成功改变了飞行动作,如下图:
最后觉得哪里不对,不是针对超类型编程吗,怎么main函数中还是针对实现编程的:
DuckGUAGUA* duckGuaGua = new DuckGUAGUA;
和
DuckZHIZHI* duckZhiZhi = new DuckZHIZHI;
我们可以这样修改main函数:
int main()
{
//DuckGUAGUA* duckGuaGua = new DuckGUAGUA;
Duck* duckGuaGua = new DuckGUAGUA;
//duckGuaGua->Display();
duckGuaGua->Swim();
duckGuaGua->PerformFly();
duckGuaGua->PerformQuack();
duckGuaGua->SetFlyBehavior(new FlyYaoBai);
duckGuaGua->PerformFly();
cout<<"************************************"<<endl;
Duck* duckZhiZhi = new DuckZHIZHI;
//duckZhiZhi->Display();
duckZhiZhi->Swim();
duckZhiZhi->PerformFly();
duckZhiZhi->PerformQuack();
system("pause");
return 0;
}
这样就好点了,而不用具体考虑实例是怎么实现的,只需要知道我要什么“鸭子”就new什么“鸭子”就可以了(Display()函数是protected类型,修改一下就可以用了)。
额,书上说学到这里,你就学了第一个设计模式了,也就是策略模式(strategy pattern),多亏了这个模式,现在系统不需要担心遇到任何的改变,因为一切变得简单了。
这里有策略模式的呆板方定义:
策略模式定义了算法簇,分别封装起来,让他们之间可以相互替换,此模式让算法的变化使用算法的客户。
ps:项目中遇到的客户很多都是只要效果就行了,你怎么干的活不重要。
记住,超类型编程和策略模式。