行为型模式关注于对象之间的通信和职责委派
解释器模式
解释器模式:给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。
如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题
备忘录模式
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
struct State {
int hp;
int mp;
};
class Memento {
State state;
public:
void setMemento(const State& state) {
this->state = state;
}
const State getState() {
return state;
}
};
class Player {
State state;
int id;
public:
Memento* createMemento() {
return new Memento;
}
void setMemento(Memento* mem) {
mem->setMemento(state);
}
};
class CareTaker {
Memento* mem = nullptr;
public:
void setMemento(Memento* mem) {
this->mem = mem;
}
Memento* getMemento() {
return this->mem;
}
};
// 使用
Player player;
CareTaker taker;
taker.setMemento(player.createMemento());
player.setMemento(taker.getMemento());
观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主体对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
class Subject;
class Observer {
protected:
Subject* sub;
public:
virtual void update() = 0;
};
class Subject {
list<Observer*> obs;
public:
void add(Observer* ob) {
obs.push_back(ob);
}
void del(Observer* ob) {
obs.remove(ob);
}
void onStateChanged() {
for (auto ob : obs) {
ob->update();
}
}
};
class BinaryObserver : Observer {
public:
BinaryObserver(Subject* sub) {
sub->add(this);
}
void update() override {
cout << "updated" << endl;
}
};
//使用
Subject* sub = new Subject;
BinaryObserver bin(sub);
sub->onStateChanged();
状态模式
状态模式允许对象在更改状态时更改其行为,其主要用于:
用来清除嵌套的条件语句。
用来实现有限状态自动机。
现在假设有一个三相开关。当点击按钮时灯的状态在 Light1, Light2, Off 三种状态切换。即实现下面的状态:
Lamp light;
light.click(); // Light 1
light.click(); // Light 2
light.click(); // Off
light.click(); // Light 1
首先需要一个对象用来储存状态:
class Context {
public:
void SetStatus(Status* status) {
delete status_;
status_ = status;
}
Status& GetStatus() {
return *status_;
}
private:
Status* status_;
};
class Lamp {
public:
Lamp() {
// 将初始状态设置为 Light1
ctx_.SetStatus(new Light1(ctx_));
}
void click() {
ctx_.GetStatus().show();
}
private:
Context ctx_;
};
然后我们需要一个状态接口:
class Status {
public:
virtual void show() = 0;
virtual ~Status() = default;
};
每当调用 show 时,调用 Context::SetStatus 将当前状态设置为下一个状态:
class Light1 : public Status {
public:
explicit Light1(Context& ctx) : ctx_(ctx) { }
void show() override {
std::cout << "Light1" << std::endl;
ctx_.SetStatus(new Light2(ctx_));
}
private:
Context& ctx_;
};
下面是其余两个状态:
class Off : public Status {
public:
explicit Off(Context& ctx) : ctx_(ctx) { }
void show() override {
std::cout << "Off" << std::endl;
ctx_.SetStatus(new Light1(ctx_));
}
private:
Context& ctx_;
};
class Light2 : public Status {
public:
explicit Light2(Context& ctx) : ctx_(ctx) { }
void show() override {
std::cout << "Light2" << std::endl;
ctx_.SetStatus(new Off(ctx_));
}
private:
Context& ctx_;
};
由于 C++ 在创建对象之前需要先看到对象声明,因此需要将 Off::Show 函数的实现放到最后。 |
空对象模式
策略模式
策略模式用于将操纵抽象成类,用于减少条件语句的产生。
struct Strategy {
virtual int Op(int num1, int num2) = 0;
};
class Plus : Strategy {
public:
int Op(int num1, int num2) override {
return num1 + num2;
}
};
class Minus : Strategy {
public:
int Op(int num1, int num2) override {
return num1 - num2;
}
};
// 使用
Plus pl;
cout << pl.Op(10, 20) << endl;
Minus mi;
cout << mi.Op(20, 30) << endl;
模板模式
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。实际上就是使用超类接口操纵子类对象。