1. 程式人生 > >C++進階(語法篇)—第11章 設計模式(2)

C++進階(語法篇)—第11章 設計模式(2)

11.3行為型模式

行為型模式:主要用於管理物件之間的演算法、關係和職責。主要講策略模式、命令模式、觀察者模式、模板模式。

11.3.1策略模式

策略模式:定義一系列演算法,將這些演算法封裝起來,並且使演算法之間可以轉換。本質是將演算法和客戶端之間隔離,使得客戶端只能通過抽象演算法類來訪問具體演算法。

假設手機需要支援3種使用模式,分別是標準模式、駕車模式、飛航模式。現在你是手機的開發者,該如何設計應用程式?如果將來手機還要支援靜音模式,又該如何設計?

#include <iostream>

 

using namespace

 std;

 

//模式:介面

class Mode

{

public:

virtual ~Mode(){}

virtual void UseMode(void) = 0;

};

//標準模式

class StandardMode:public Mode

{

public:

virtual void UseMode(void){cout<<"Standard Mode!"<<endl;};

};

//駕車模式

class DrivingMode:public

 Mode

{

public:

virtual void UseMode(void){cout<<"Driving Mode!"<<endl;};

};

//飛航模式

class FlightMode:public Mode

{

public:

virtual void UseMode(void){cout<<"Flight Mode!"<<endl;};

};

//手機模式

class PhoneMode

{

private

:

Mode * mode;

public:

PhoneMode(Mode * mode)

{

this->mode = mode;

}

void UseMode()

{

mode->UseMode();

}

};

 

int main(int argc,char ** argv)

{

StandardMode * sm = new StandardMode;

DrivingMode * dm = new DrivingMode;

FlightMode * fm = new FlightMode;

 

PhoneMode pm1(sm);

PhoneMode pm2(dm);

PhoneMode pm3(fm);

pm1.UseMode();

pm2.UseMode();

pm3.UseMode();

 

delete sm;

delete dm;

delete fm;

 

return 0;

}

執行結果:

Standard Mode!

Driving Mode!

Flight Mode!

策略模式結構圖:

Context:環境角色,持有一個對Stratery的引用,最終給客戶端使用。相當於PhoneMode。

Stratery:抽象策略類,相當於Mode。

ConcreteStratery:具體策略類,相當於StandardMode、DrivingMode、FlightMode。

策略模式和簡單工廠模式看起來很相似,都是通過多型來實現不同子類的選取。簡單工廠模式是工廠根據需求來建立物件(產品),然後將事情交給物件去完成。策略模式是環境角色根據自己選擇的策略來建立物件,這個物件是其本身,因此所有的事情還是自己來完成。難以理解的話,可以看看模式結構圖。

11.3.2命令模式

餐館服務員接收到一份訂單:客戶要求先來一份烤肉再來一份炒菜(烤肉在前,炒菜在後);服務員接收到烤肉命令和炒菜命令,然後執行命令(但命令的真正實現不是服務員);廚師接收到烤肉命令和炒菜命令後,開始幹活。

//Receiver.h

#pragma once

#include <iostream>

using namespace std;

//廚師

class Cook

{

public:

//烤肉

void Barbecue(void)

{

cout << "Barbecue..." << endl;

}

//炒菜

void StirFry(void)

{

cout << "StirFry" << endl;

}

};

//Command.h

#pragma once

#include "Receiver.h"

class Command

{

public:

Command() {}

Command(Cook * cook)

{

this->cook = cook;

}

virtual void execute(void) = 0;

protected:

Cook * cook;

};

//烤肉命令

class BarbecueCommand :public Command

{

public:

BarbecueCommand() {}

BarbecueCommand(Cook * cook)

{

this->cook = cook;

}

void execute(void)

{

cout << "BarbecueCommand::execute" << endl;

cook->Barbecue();

}

};

 

class StirFryCommand :public Command

{

public:

StirFryCommand() {}

StirFryCommand(Cook * cook)

{

this->cook = cook;

}

void execute(void)

{

cout << "StirFryCommand::execute" << endl;

cook->StirFry();

}

};

//Invoker.h

#pragma once

#include "Command.h"

#include <list>

class Waiter

{

public:

Waiter() {};

// 新增命令

void addCmd(Command *cmd)

{

cmds.push_back(cmd);

}

// 刪除命令

void deleteCmd(Command *cmd)

{

cmds.remove(cmd);

}

// 執行命令

void notify()

{

for (list<Command *>::iterator it = cmds.begin(); it != cmds.end(); ++it)

{

(*it)->execute();

}

}

 

private:

std::list<Command *> cmds;  // 命令佇列

};

//main.cpp

#include <iostream>

#include "Invoker.h"

#include "Receiver.h"

#include "Command.h"

 

using namespace std;

 

int main(int argc, char ** argv)

{

Cook * ck = new Cook;

BarbecueCommand * pBarCom = new BarbecueCommand(ck);

StirFryCommand * pStiCom = new StirFryCommand(ck);

 

Waiter wait;

wait.addCmd(pBarCom);

wait.addCmd(pStiCom);

wait.notify();

 

delete ck;

delete pBarCom;

delete pStiCom;

return 0;

}

執行結果:

BarbecueCommand::execute

Barbecue...

StirFryCommand::execute

StirFry

命令模式結構圖:

Invoker:命令的持有者和執行者;

Command:命令的抽象類;

ConcreteCommand:命令的具體類;

Receiver:命令的接收者和實際執行者;

命令模式難以理解,舉個實際例子:打車客戶(Client)發出打車命令->滴滴平臺(Invoker)接收到命令,然後發出打車命令->滴滴師傅(Receiver)接收到打車命令,然後去目標地點接人。通用例子:Client發出命令->Invoker持有,加入命令佇列,然後執行命令->Receiver接收和開始幹活。

11.3.3觀察者模式

觀察者模式:定義物件間一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴它的物件得到通知並自動更新。

假設小明爸爸和小明媽媽關注小明的成績,當小明考試成績出來時,需要及時通知小明的父母,該如何設計這個程式?

#include <iostream>

#include <list>

using namespace std;

 

class Subject;

class Observer;

 

//抽象目標:Subject

class Subject

{

public:

virtual void Attach(Observer *) = 0;//註冊觀察者

virtual void Detach(Observer *) = 0;//登出觀察者

virtual void Notify() = 0;//通知觀察者

};

//抽象觀察者:Observer

class Observer

{

public:

virtual void Update(double) = 0;//更新狀態

};

//具體目標:ConcreteSubject

class Student : public Subject

{

private:

list<Observer *> pObserverList;//觀察者列表

double achievement;

public:

void Attach(Observer * pObserver)

{

pObserverList.push_back(pObserver);

}

void Detach(Observer * pObserver)

{

pObserverList.remove(pObserver);

}

void Notify()

{

for(list<Observer *>::iterator it = pObserverList.begin(); it != pObserverList.end(); ++it)

{

(*it)->Update(achievement);

}

}

void setValue(double achievement)

{

this->achievement = achievement;

}

};

//具體觀察者:ConcreteObserver

class Father :public Observer

{

private:

Subject * pSubject;

public:

Father() {}

Father(Subject * pSubject)

{

this->pSubject = pSubject;

}

void Update(double achievement)

{

cout <<"孩子成績:" << achievement << endl;

}

};

class Mother : public Observer

{

private:

Subject * pSubject;

public:

Mother() {}

Mother(Subject * pSubject)

{

this->pSubject = pSubject;

}

void Update(double achievement)

{

cout << "孩子成績:" << achievement << endl;

}

};

 

int main(int argc, char ** argv)

{

//建立具體目標

Student * xiaoming = new Student();

xiaoming->setValue(60);

 

//建立具體觀察者

Father * xmF = new Father(xiaoming);

Mother * xmM = new Mother(xiaoming);

 

//加入觀察佇列

xiaoming->Attach(xmF);

xiaoming->Attach(xmM);

 

//通知觀察者

xiaoming->Notify();

 

delete xiaoming;

delete xmF;

delete xmM;

return 0;

}

執行結果:

孩子成績:60

孩子成績:60

觀察者模式結構圖:

Subject(抽象目標):知道所有觀察者,並提供註冊和刪除觀察者的介面;

Observer(抽象觀察者):為具體觀察者提供介面,在得到目標的通知時進行自我更新。

ConcreteSubject(具體目標):當具體目標的狀態發生改變,通知所有觀察者。

ConcreteObserver(具體觀察者):實現更新介面Update。