@brief
学习《Head First设计模式》中第一节 - “策略模式”
(由于原书全是 java,自己还不是很适应)
策略模式的定义:
策略模式顶一个一个算法族,分别封装起来,使得它们之间可以互相交换。
策略让算法的变化独立于使用它的客户。
设计原则:
针对接口编程,而不是针对实现编程。
问题引入:
当设计完 Duck类后,有的派生类duck 需要 fly() 方法。
=> 一种做法是:直接在 class Duck() 中添加 fly()方法。
=> 但是不是所有的 duck 都能够飞,所以这种做法是错误的(所有的派生类都可以调用了)
“总结”: 不能通过 继承 来达到 复用 的目的,当涉及到 维护 时会很麻烦。
解决办法:
实行功能分离:
=> 把变化的部分取出并封装,这样,以后就可以修改或扩展这个部分,而不会影响其它不需要变化的部分。
=> 这样系统会更有弹性。
main.cpp
/**
* @file main.cpp
* @author GaoJune (gaojune_better@q.com)
* @version 0.1
* @date 2022-04-28
* @copyright Copyright (c) 2022
*
* 文件介绍:
* Duck.h 为最基本的class,里面封装了2个接口,以及所有 duck 的公共函数
* 该 “ has-A ” 中,每只鸭子有一个FlayBehavior和QuackBehavior,以委托飞行和叫。
* FlayBehavior.h 和 QuackBehavior.h 分别对 fly()、quack() 进行封装
*/
#include <iostream>
#include "Duck.h"
// 前置声明
class Duck;
class FlyBehavior;
class QuackBehavior;
// 设计鸭子类 MiniDuckSimulator,并为其添加属性
class MiniDuckSimulator : public Duck{
public:
MiniDuckSimulator() {
std::cout << "ctor MiniDuckSimulator" << std::endl;
// 给该类添加一些新特性
_fly_behavior = new FlyWithWings();
_quack_behavior = new Squeak();
}
~MiniDuckSimulator() {
std::cout << "dtor MiniDuckSimulator" << std::endl;
}
};
int main( ){
// 开始测试
Duck* mallard = new MiniDuckSimulator();
mallard->Swim();
mallard->Display();
mallard->PerformFly();
mallard->PerformQuack();
// 改变鸭子的飞行、叫声
std::cout << "改变鸭子飞行、叫声 技能" << std::endl;
mallard->SetFlyBehavior( new FlyNoWay() );
mallard->SetQuackBehavior( new MuteQuack() );
mallard->PerformFly();
mallard->PerformQuack();
return 0;
}
Duck.h
/**
* @brief:
* Duck类中包含两个抽象类: FlyBehavior、 QuackBehavior
* FlyBehavior 接口:对 fly 做了封装
* QuackBehavior 接口:对 Quack(嘎嘎)做了封装
*/
#pragma once
#include <iostream>
#include "FlyBehavior.h"
#include "QuackBehavior.h"
class Duck{
public:
Duck(){
std::cout << "ctor Duck" << std::endl;
}
~Duck(){
std::cout << "dtor Duck" << std::endl;
delete _fly_behavior;
delete _quack_behavior;
}
public:
// 所有鸭子的公共行为
void Swim( ){
std::cout << "Ducks can swim!" << std::endl;
}
void Display( ){
std::cout << "Duck's Display" << std::endl;
}
// 委托给接口执行
void PerformFly( ){
_fly_behavior->Fly();
}
void PerformQuack( ){
_quack_behavior->quack();
}
// 改变 duck 的技能
// eg. 传入 new FlyNoWay()
void SetFlyBehavior( FlyBehavior *fb ){
_fly_behavior = fb;
}
void SetQuackBehavior( QuackBehavior *qb ){
_quack_behavior = qb;
}
// 这里不能设置 private,不然无法修改指针指向
protected:
FlyBehavior* _fly_behavior;
QuackBehavior* _quack_behavior;
};
FlyBehavior.h
/**
* @brief:
* FlyBehavior :飞行行为基类
* class FlyWithWings、class FlyNoWay会继承该接口
*/
#pragma once
#include <iostream>
class FlyBehavior{
public:
FlyBehavior(){
std::cout << "ctor FlyBehavior" << std::endl;
}
~FlyBehavior(){
std::cout << "dtor FlyBehavior" << std::endl;
}
public:
virtual void Fly( ) = 0;
};
/**
* @brief:
* FlyWithWings :对 能飞 的鸭子进行飞行实现
*/
class FlyWithWings : public FlyBehavior{
public:
FlyWithWings(){
std::cout << "ctor FlyWithWings" << std::endl;
}
~FlyWithWings(){
std::cout << "dtor FlyWithWings" << std::endl;
}
public:
void Fly( ){
std::cout << "I'm flying!" << std::endl;
}
};
/**
* @brief:
* FlyNoWay :对不能飞的鸭子进行飞行实现
*/
class FlyNoWay : public FlyBehavior{
void Fly( ){
std::cout << "I can't fly" << std::endl;
}
};
QuackBehavior.h
/**
* @brief
* QuackBehavior :所有动作行为基类
* class Quack、class MuteQuack、Squeak 会继承该接口
*/
#pragma once
#include <iostream>
class QuackBehavior{
public:
QuackBehavior() = default;
~QuackBehavior() = default;
public:
virtual void quack( ) = 0;
};
// 嘎嘎叫
class Quack : public QuackBehavior{
public:
Quack(){
std::cout << "ctor Quack" << std::endl;
}
~Quack(){
std::cout << "dtor Quack" << std::endl;
}
public:
void quack( ){
std::cout << "Quack" << std::endl;
}
};
// 不会叫
class MuteQuack : public QuackBehavior{
public:
MuteQuack(){
std::cout << "ctor MuteQuack" << std::endl;
}
~MuteQuack(){
std::cout << "dtor MuteQuack" << std::endl;
}
public:
void quack( ){
std::cout << " <<Slience>> " << std::endl;
}
};
// 吱吱叫
class Squeak : public QuackBehavior{
public:
Squeak(){
std::cout << "ctor Squeak" << std::endl;
}
~Squeak(){
std::cout << "dtor Squeak" << std::endl;
}
public:
void quack( ){
std::cout << "Squeak" << std::endl;
}
};