目的
从范围来看:
非常基础设计模式,在面向对象系统中有着大量的应用。它用最简洁的机制(虚函数的多态性) 为很多应用程序框架提供了灵活的扩展点,是代码复用方面的基本实现结构
“不要调用我,让我来调用你”的反向控制结构是Template Method的典型应用
在具体实现方面,被Template Method调用的虚方法可以具有实现,也可以没有任何实现(抽象方法、纯虚方法),但一般推荐将它们设置为protected方法
int Application::run()
{
PVRFrameEnableControlWindow(false);
UINT TARGET_RESOLUTION = 1; // 1 millisecond target resolution
TIMECAPS tc;
UINT wTimerRes = 0;
if (TIMERR_NOERROR == timeGetDevCaps(&tc, sizeof(TIMECAPS)))
{
wTimerRes = std::min(std::max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);
timeBeginPeriod(wTimerRes);
}
LARGE_INTEGER nLast;
LARGE_INTEGER nNow;
QueryPerformanceCounter(&nLast);
initGLContextAttrs();
if (!applicationDidFinishLaunching())
{
return 1;
}
auto director = Director::getInstance();
auto glview = director->getOpenGLView();
glview->retain();
LONGLONG interval = 0LL;
LONG waitMS = 0L;
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
while(!glview->windowShouldClose())
{
QueryPerformanceCounter(&nNow);
interval = nNow.QuadPart - nLast.QuadPart;
if (interval >= _animationInterval.QuadPart)
{
nLast.QuadPart = nNow.QuadPart;
director->mainLoop();
glview->pollEvents();
}
else
{
waitMS = (_animationInterval.QuadPart - interval) * 1000LL / freq.QuadPart - 1L;
if (waitMS > 1L)
Sleep(waitMS);
}
}
if (glview->isOpenGLReady())
{
director->end();
director->mainLoop();
director = nullptr;
}
glview->release();
if (wTimerRes != 0)
{
timeEndPeriod(wTimerRes);
}
return 0;
}
#include "main.h"
#include "AppDelegate.h"
USING_NS_CC;
int WINAPI _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// create the application instance
AppDelegate app;
return Application::getInstance()->run();
}
这里为cocos2dx的main.cpp源码,这里AppDelegate很明显是cocos2dx框架提供的对象,我们要做的只是修改run执行的对象,对run不需要更改
对该模式进行分析:run()方法是较为稳定的方法,开发者需要修改的只是run()中的director->mainLoop()
作为模板的框架提供相对静止的run(),作为开发者为框架提供比较动态的mainloop(),再有框架来调用即可
将框架内部实现细节对开发者隐藏,让开发者仅对自己需要注意的部分花费心思
在软件构建中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不适用的算法也是一种性能负担
/**
* 常规写法
*/
enum CalculateType
{
Tpye_1,
Tpye_1,
Tpye_1,
};
class CalculateClass
{
CalculateType _type;
public:
void calculateFunc()
{
switch (_type)
{
case CalculateType::Tpye_1:
// 算法1
break;
case CalculateType::Tpye_2:
// 算法2
break;
case CalculateType::Tpye_3:
// 算法3
break;
default:
break;
}
}
}
该方法虽然能够针对不同类型做不同处理,但是不符合开闭原则:对扩展开放对修改关闭,这里如果添加新的类型只能修改源码才能继续运行
/**
* 策略模式
*/
class CalculateCls
{
public:
virtual int Calculate() = 0;
virtual ~CalculateCls() {}
};
class CalculateType_1 : public CalculateCls
{
public:
virtual int Calculate() override
{
// 算法1
}
};
class CalculateType_2 : public CalculateCls
{
public:
virtual int Calculate() override
{
// 算法2
}
};
class CalculateType_3 : public CalculateCls
{
public:
virtual int Calculate() override
{
// 算法3
}
};
class CalculateClass
{
private:
CalculateCls *_cal;
public:
void setCalculateCls(CalculateCls *cls)
{
this->_cal = cls;
}
// 使用策略模式之后,calculateFunc方法无需根据类型修改,类型增加删除也不会影响该方法,需要修改只是设置的CalculateCls对象
void calculateFunc()
{
cls.Calculate();
}
}
警惕if~else和 switch的使用,有些情况使用策略模式来替换是更好的选择
需要为某些对象建立一种“通知依赖关系”——一个对象的状态发生改变,所有的依赖对象都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好的抵御变化
/**
* 常规写法
*/
class ReadFile
{
private:
PrograssBar *_progreess;
public:
ReadFile(const std::string &filename)
{
// ....
}
void setProgress(ProgressBar *progress)
{
this->_progreess = progress;
}
void read()
{
bool readFinish = false;
while (readFinish)
{
// ... 读取处理
_progreess->updateProgress();
}
}
};
该写法不符合依赖倒置原则,这里依赖的具体的实现细节,如果后面不想用progress(进度条)而是想要文本框,岂不是又需要修改代码吗
/**
* 观察者模式
*/
class Observer // 基类
{
public:
virtual void update(int val) = 0;
virtual void ~Observer() {}
};
class PrograssBar : public Forum, public Observer{
// .... 进度条处理
// Forum是普通的显示基类
virtual void update(int val) override{
// 更新进度条操作
}
};
class Text: public Forum, public Observer{
// .... 文本处理
// Forum是普通的显示基类
virtual void update(int val) override{
// 更新文本内容
}
};
class ReadFile
{
private:
Observer *_observer ;
public:
ReadFile(const std::string &filename)
{
// ....
}
void setProgress(Observer *progress)
{
this->_progreess = progress;
}
void read()
{
bool readFinish = false;
while (readFinish)
{
// ... 读取处理
_progreess->update();
}
}
};
某些情况下过度地使用继承来扩展对象的功能,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且伴随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的碰撞
/**
* 常规写法
*/
// 接口
class MyStream{
virtual char Read(int number) = 0;
virtual void Seek(int pos) = 0;
virtual void Write(char data) = 0;
virtual void ~MyStream() {};
};
// 文件流
class FileStream : public MyStream{
public:
virtual char Read(int number){
}
virtual void Seek(int pos){
}
virtual void Write(char data){
}
virtual FileStream (){}
};
// 网络流
class NetworkStream : public MyStream{
// ....
};
// 加密文件流
class CryptoFileStream : public FileStream{
public:
virtual char Read(int number){
// 加密操作
FileStream::Read(number);
// 加密操作
}
virtual void Seek(int pos){
// 加密操作
FileStream::Seek(pos);
// 加密操作
}
virtual void Write(char data){
// 加密操作
FileStream::Write(data);
// 加密操作
}
};
// 网络流加密
class CryptoNetworkStream : public NetworkStream {
// ...
};
// 文件流缓冲
class BufferedFileStream : public FileStream{
// ...
};
// 网络流流缓冲
class BufferedNetworkStream : public NetworkStream{
// ...
};
CryptoNetworkStream和CryptoFileStream的加密操作几乎相同,BufferedFileStream和BufferedNetworkStream缓存操作几乎相同,除了内部调用read、write和Seek调用的基类函数不同,可见这里存在明显的代码冗余
/**
* 装饰模式
*/
// 接口
class MyStream{
virtual char Read(int number) = 0;
virtual void Seek(int pos) = 0;
virtual void Write(char data) = 0;
virtual void ~MyStream() {};
};
// 文件流
class FileStream : public MyStream{
public:
virtual char Read(int number){
}
virtual void Seek(int pos){
}
virtual void Write(char data){
}
virtual FileStream (){}
};
// 网络流
class NetworkStream : public MyStream{
// ....
};
// 加密流
class CryptoStream : public MyStream{
MyStream* stream;
public:
CryptoStream (MyStream* str) : stream(str) {}
virtual char Read(int number){
// 加密操作
stream->Read(number);
// 加密操作
}
virtual void Seek(int pos){
// 加密操作
stream->Seek(pos);
// 加密操作
}
virtual void Write(char data){
// 加密操作
stream->Write(data);
// 加密操作
}
};
// 缓冲流
class BufferedStream : public MyStream{
MyStream* stream;
public:
BufferedStream(MyStream* str) : stream(str) {}
virtual char Read(int number){
// 缓冲操作
stream->Read(number);
// 缓冲操作
}
virtual void Seek(int pos){
// 缓冲操作
stream->Seek(pos);
// 缓冲操作
}
virtual void Write(char data){
// 缓冲操作
stream->Write(data);
// 缓冲操作
}
};
class Messager{
public:
virtual void SendMessage() = 0;
virtual void WriteText() = 0;
virtual ~Messager() {}
};
// 平台实现
class PcMessagerBase : public Messager{
virtual void SendMessage() {
}
virtual void WriteText() {
}
};
// 移动
class MobileMessagerBase : public Messager{
virtual void SendMessage() {
}
virtual void WriteText() {
}
};
在软件系统中,经常面临创建对象的工作,有需求的变化,需要创建的对象的具体类型经常变化
// 分割器
class Spliter{ };
class BinarySpliter : public Spliter{}; // 二进制分割器
class PictureSpliter : public Spliter{};// 图片分割器
class TxtSpliter : public Spliter{};//文本分割器
class MainForum : public Forum{
public:
void Click(const std::string &file){
Spliter* spliter = new BinarySpliter();
// ...
}
};
这里使用的分割器依赖了具体类
class Spliter{ };
class BinarySpliter : public Spliter{}; // 二进制分割器
class PictureSpliter : public Spliter{};// 图片分割器
class TxtSpliter : public Spliter{};//文本分割器
class SpliterFactory{
public:
Spliter* CreateSpliter() = 0;
virtual ~SpliterFactory(){}
};
class BinarySpliterFactory{
public:
Spliter* CreateSpliter() {
return new BinarySpliter();
}
};
class PictureSpliterFactory{
public:
Spliter* CreateSpliter() {
return new PictureSpliter ();
}
};
class TxtSpliterFactory{
public:
Spliter* CreateSpliter() {
return new TxtSpliter ();
}
};
class MainForum : public Forum{
private:
SpliterFactory* _spliterFactory;
public:
void setSpliteerFactory(SpliterFactory* spliterFactory){
_spliterFactory = spliterFactory;
}
void Click(const std::string &file){
Spliter* spliter = _spliterFactory->CreateSpliter();
// ...
}
};
把动态的(具体是哪个工厂也需要明确指出)部分赶出了该类的设计
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂模式使得一个类的实例化延迟到子类
在软件系统中,经常面临这“一系列相互依赖的对象”的创建工作;同时,由于需求的变化,往往存在更多系列对象的创建工作
class DBConnection {};
class DBCommand();
class DBDataReader();
class DBConnectionFactory {};
class DBCommandFactory {};
class DBDataReaderFactory {};
class SQLServerConnection:public DBConnection {};
class SQLServerCommand:public DBCommand {};
class SQLServerDataReader:public DBDataReader{};
class SQLServerConnectionFactory:public DBConnectionFactory {};
class SQLServerCommandFactory:public DBCommandFactory {};
class SQLServerDataReaderFactory:public DBDataReaderFactory {};
class OracleConnection : public DBConnection {};
class OracleCommand : public DBCommand{};
class OracleDataReader : public DBDataReader {};
class OracleConnectionFactory :public DBConnectionFactory {};
class OracleCommandFactory :public DBCommandFactory {};
class OracleDataReaderFactory :public DBDataReaderFactory {};
class MySqlConnection : public DBConnection {};
class MySqlCommand : public DBCommand{};
class MySqlDataReader : public DBDataReader{};
class MySqlConnectionFactory :public DBConnectionFactory {};
class MySqlCommandFactory :public DBCommandFactory {};
class MySqlDataReaderFactory :public DBDataReaderFactory {};
class Dao{
private:
DBConnectionFactory * _connection;
DBCommandFactory * _command;
DBDataReaderFactory * _dataReader;
public:
std::vector<Student> getAllStudent(){
// ...
}
};
存在一个问题是:Connection、Command、DataReder必须是同一系列的,不同系列肯定出错
class DBConnection {};
class DBCommand();
class DBDataReader();
class DBFactory{
virtual DBConnection* CreaeConnection() = 0;
virtual DBCommand* CreaeCommand() = 0;
virtual DBDataReader* CreaeDataFactory() = 0;
};
class Dao{
private:
DBFactory * _factory;
public:
std::vector<Student> getAllStudent(){
// ...
}
};
提供一个接口,让该结构负责创建一系列相关或者互相依赖的对象,无需执行他们具体的类
在软件系统中,经常面临着某些结构复杂的对象的创建工作,由于需求的变化,这些对象经常面临这剧烈的变化,但是他们却拥有比较稳定一直的接口
使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象
/**
* Prototype 原型模式
* 由于不知道未来Image的子类的名称,所以Image使用一个_prototypes来记录子类的原型
* 原型需要实现自己的Clone()函数,方便Image通过Type来管理和创建
* 原型需要实现自己的returnType()函数,方便Image来获得Type做一些判断
* 原型需要一个static的自己并且在默认构造函数中将自己添加到Image的管理中
*
* ——————————————————————————————————————————————————————
*
* 通过上面的操作,可以用Image创建出其子类,不管这个子类在当时知不知道
* 原型模式的重点是Clone和基类的管理,子类的构造函数在protected和private是因为这些子类不准备自己创建,而是通过Image来创建
**/
enum imageType
{
LAST,
SPOT
};
class Image
{
public:
virtual void draw() = 0;
static Image *findAndClone(imageType type)
{
for (int i = 0; i < _nextSlot; i++)
{
if (_prototypes[i]->returnType() == type)
{
return _prototypes[i]->Clone();
}
}
}
protected:
virtual imageType returnType() = 0;
virtual Image *Clone() = 0;
static void addPrototype(Image *image)
{
_prototypes[_nextSlot++] = image;
}
private:
static Image *_prototypes[10];
static int _nextSlot;
};
Image *Image::_prototypes[];
int Image::_nextSlot;
class NewImageType : public Image
{
public:
Image *Clone() override
{
return new NewImageType(1);
}
imageType returnType() override
{
return imageType::LAST;
}
void draw() override
{
std::cout << "NewImageType" << std::endl;
}
protected:
NewImageType(int _dummy) // 为了跟默认构造函数做区别,所以加了个参数,因为默认构造函数是注册用的
{
_id = _count++;
}
private:
static NewImageType _newImageType; // 创建一个static的自己,调用下面的默认构造,将自己添加到Image的管理中
NewImageType()
{
addPrototype(this); // 将自己添加到Image的管理中
}
int _id;
static int _count;
};
NewImageType NewImageType::_newImageType;
int NewImageType::_count = 1;
在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临这剧烈的变化,但是将他们组合在一起的算法却相对稳定
构建器:将一个复杂对象的构建与其表示相分离,使得同样的构建过程(稳定)可以创建不同的表示(变化)
class House{
public:
void init(){
this->BuilderPart1();
// ...其他操作
this->BuilderPart2();
// ...其他操作
this->BuilderPart3();
// ...其他操作
this->BuilderPart4();
// ...其他操作
}
virtual ~House(){}
protected:
virtual void BuilderPart1() = 0;
virtual void BuilderPart2() = 0;
virtual void BuilderPart3() = 0;
virtual void BuilderPart4() = 0;
};
class StoneHouse : public House{
virtual void BuilderPart1() {}
virtual void BuilderPart2() {}
virtual void BuilderPart3() {}
virtual void BuilderPart4() {}
};
int main()
{
StoneHouse stoneHouse = new StoneHouse ();
stoneHouse->init();
return 0;
}
这个还能继续优化,将init部分拆出来等
在软件系统中,经常有一些特殊的类,必须保证他们在系统中只存在一个实例,才能确保他们的逻辑正确性以及良好的效率
/**
* 单例模式
*
*/
class Singleton
{
private:
Singleton(); // 构造需要是私有 防止外部创建
Singleton(const Singleton &other); // 拷贝构造需要是私有 防止外部创建
public:
static Singleton *getInstance() // 多线程下不安全,可能多次执行new操作
{
if (m_instance == nullptr)
{
m_instance = new Singleton();
}
return m_instance;
}
static Singleton *getInstance() //加锁 保证多线程安全 但是代价较高每次调用getInstance都会加锁
{
Lock lock;
if (m_instance == nullptr)
{
m_instance = new Singleton();
}
return m_instance;
}
static Singleton *getInstance() //双检查锁,但由于内存读写reorder不安全
{
if (m_instance == nullptr)
{
Lock lock;
if (m_instance == nullptr)
{
m_instance = new Singleton();
}
}
return m_instance;
}
static Singleton *m_instance;
};
Singleton *Singleton::m_instance = nullptr;
class Single
{
public:
static Single &GetInstance();
private:
Single();
~Single();
Single(const Single &signal);
const Single &operator=(const Single &signal);
};
Single &Single::GetInstance()
{
static Single signal;
return signal;
}
单例模式需要注意线程安全问题
注意构造、拷贝构造的位置,防止外部有人主动new出对象
在软件系统采用纯粹面向对象方案的问题在于大量细粒度的对象会很快充斥再系统中,从而带来很高的运行时代价——主要指内存需求方面的代价
运用共享技术有效地支持大量细粒度的对象
class Font
{
private:
std::string key; // 字体的key,通过key获得相关的资源
public:
Font(const string &key)
{
}
};
class FontFactory
{
private:
std::map<std::string, Font *> fontPool;
public:
Font *GetFontData(const std::string &key)
{
map<std::string, Font *>::iterator item = fontPool.find(key);
if (item != fontPool.end())
{
return fontPool[key];
}
else
{
Font *font = new Font(key);
fontPool[key] = font;
return font;
}
}
}
新增一层接口,隐藏内部模块的对象接口,同时也可以方便外部调用
在面向对象系统中,有些独享由于某些原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问会给使用者、或者系统结构带来很多麻烦
在软件系统中,由于应用环境的变化,常常需要将一些显存的对象放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的
适配器模式是将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
在软件构建过程中,经常会出现多个对象互相关联交互的情况,对象之间常常会维持一种复杂的引用关系,如果遇到一些需求的更改,这种直接的引用关系将面临不断的变化
用一个中介对象来封装(封装变化)一系列的对象交互。中介者使各个对象不需要显式的相互引用(编译时依赖->运行时依赖),从而使其耦合松散(管理变化),而且可以独立地改变它们之间的交互
在组件构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?状态模式为这问题提供了解决方案
某些对象的状态改变,他的行为也随之发生变化,比如文档处于只读状态 状态模式:允许一个对象在其内部状态改变时改变它的行为,从而使对象看起来似乎修改了其行为
enum NetworkState {
Network_Open,
Network_Close,
Network_Connect,
};
class NetworkProcessor
{
NetworkState _state;
public:
void Operatrion1()
{
switch (_state)
{
case NetworkState::Network_Open:
// 一些操作
_state = NetworkState::Close;
break;
case NetworkState::Network_Close:
// 一些操作
_state = NetworkState::Network_Connect;
break;
case NetworkState::Network_Connect:
// 一些操作
_state = NetworkState::Network_Open;
break;
default:
break;
}
}
}
跟以前策略模式的反例一样 违反了开闭原则
/**
* 状态模式
*
*/
enum NetworkState {
Network_Open,
Network_Close,
Network_Connect,
};
class NetworkStateBase
{
public:
virtual void Operatrion1() = 0;
virtual ~NetworkStateBase();
NetworkStateBase *_state;
};
class OpenState : public NetworkStateBase
{
public:
static OpenState *getInstance()
{
static OpenState state;
return &state;
}
void Operatrion1()
{
// Open的一些操作
this->_state = CloseState::getInstance();
}
};
class CloseState : public NetworkStateBase
{
public:
static CloseState *getInstance()
{
static CloseState state;
return &state;
}
void Operatrion1()
{
// Close的一些操作
this->_state = ConnectState::getInstance();
}
};
class ConnectState : public NetworkStateBase
{
public:
static ConnectState *getInstance()
{
static ConnectState state;
return &state;
}
void Operatrion1()
{
// Connect的一些操作
this->_state = OpenState::getInstance();
}
}
class NetworkProcessor
{
private:
NetworkStateBase *_netstate;
public:
NetworkProcessor(NetworkStateBase *pState)
{
_netstate = pState;
}
void Operatrion1()
{
_netstate->Operatrion1();
_netstate = _netstate->_state;
}
}
这里每个状态一个单例模式,是因为很多情况下单例就行了,具体情况具体分析
这个每个状态都单独写了一个类,保证NetworkProcessor的开闭原则
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态
class Moment{ // 备忘录
private:
std::string state;
public:
Moment(std::string s) : state(s) {}
std::string getState() const { return this->state; }
void setState(const std::string& s) { this->state = s; }
};
class Originator { // 原发器
private:
std::string state;
public:
Moment createMoment(){
Moment moment(state);
return moment; // 记录状态
}
void setMoment(const Moment &m){
this->state = m.getState(); // 恢复状态
}
};
这里的记录状态可能不止一个state字符串,可能存在很多其他信息,存在一些特殊的序列化技术或内存编码技术记录状态
软件在某些情况下,客户代码过多的依赖于对象容器复杂的内部实现结构,对象容器内部实现结构(非抽象接口)的变化将引起客户代码的频繁变化,带来了代码的维护性、扩展性等弊端
组合模式将对象组合成树形结构以表示部分-整体的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性(稳定)
/**
* Composite 组合设计模式
* 例子:需要一个文件管理系统(包括文件和文件夹)
* Component作为基类、Primitive作为单个文件、Composite作为文件
**/
class Component
{
private:
int value;
public:
Component(int val) { value = val; }
virtual void add() {}
};
class Primitive : public Component // 文件
{
public:
Primitive(int val) : Component(val) {}
};
class Composite : public Component // 文件夹
{
std::vector<Component *> _c; // 既可以存储文件也可以存储文件夹
public:
Composite(int val) : Component(val) {}
void add(Component *elem)
{
_c.push_back(elem);
}
};
通过组合模式的方式,将树形结构的访问限制在了这个类的内部
在软件构建中,集合对象内部结构常常变化各异。但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码透明地访问其中包含的元素;同时这种透明遍历也为同一种算法在多种集合对象上进行操作提供了可能
使用面向对象技术将这种遍历机制抽象为迭代器对象为应对变化中的集合对象提供了一种优雅的方式
迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而 又不暴露(稳定)该对象的内部表示
Iterator.h
template<class Item>
class Iterator
{
public:
Iterator() {};
virtual ~Iterator() {};
virtual void first() = 0;
virtual void next() = 0;
virtual Item *curItem() = 0;
virtual bool isDone() = 0;
};
ConcreteIterator.h
#pragma once
#include "Iterator.h"
template<class Item>
class ConcreteIterator : public Iterator <Item>
{
public:
ConcreteIterator(Aggregate<Item> *a) :aggr(a), cur(0) {};
virtual ~ConcreteIterator() {};
virtual void first();
virtual void next();
virtual Item *curItem();
virtual bool isDone();
private:
Aggregate<Item> *aggr;
int cur;
};
template<class Item>
void ConcreteIterator<Item>::first()
{
cur = 0;
}
template<class Item>
void ConcreteIterator<Item>::next()
{
if (cur < aggr->getSize())
cur++;
}
template<class Item>
Item *ConcreteIterator<Item>::curItem()
{
if (cur < aggr->getSize())
{
return &(*aggr)[cur];
}
else
{
return NULL;
}
}
template<class Item>
bool ConcreteIterator<Item>::isDone()
{
return cur >= aggr->getSize();
}
Aggregate.h
#pragma once
#include "Iterator.h"
template<class Item>
class Aggregate{
public:
Aggregate() {};
virtual ~Aggregate() {};
virtual void pushData(Item item) = 0;
virtual Iterator<Item>* createIterator() = 0;
virtual Item& operator[](int index) = 0;
virtual int getSize() = 0;
};
ConcreteAggregate.h
#pragma once
#include <vector>
#include "Aggregate.h"
#include "ConcreteIterator.h"
using namespace std;
template <class Item>
class ConcreteAggregate : public Aggregate<Item>
{
public:
ConcreteAggregate() {};
virtual ~ConcreteAggregate() {};
virtual void pushData(Item item);
virtual Iterator<Item>* createIterator();
virtual Item& operator[](int index);
virtual int getSize();
private:
vector<Item> data;
};
template <class Item>
void ConcreteAggregate<Item>::pushData(Item item)
{
data.push_back(item);
}
template <class Item>
Iterator<Item>* ConcreteAggregate<Item>::createIterator()
{
return new ConcreteIterator<Item>(this);
}
template <class Item>
Item& ConcreteAggregate<Item>::operator[](int index)
{
return data[index];
}
template <class Item>
int ConcreteAggregate<Item>::getSize()
{
return data.size();
}
测试代码
int main(int argc, char *argv[])
{
Aggregate<int> * aggr = new ConcreteAggregate<int>();
aggr->pushData(3);
aggr->pushData(2);
aggr->pushData(1);
Iterator<int> * it = aggr->createIterator();
for (it->first(); !it->isDone(); it->next())
{
std::cout << *it->curItem() << std::endl;
}
delete it;
delete aggr;
}
版权声明:本文为CSDN博主「MachineChen」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/u012611878/article/details/78010435 代码来源
在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显式指定,将必不可少地带来请求发送者与接受者的紧耦合
职责链模式使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连城一条链,并沿着这条链传递请求,知道有一个对象处理它为止
class Request
{
std::string description;
RequestType reqType;
public:
Request(const std::string &desc, RequestType &type) : description(desc), reqType(type) {}
RequestType getRequestType() { return reqType; }
const std::string &GetDescription() { return description; }
};
class ChainHandler
{
ChainHandler *nextChain;
void sendRequestToNExtHandler(const Request &rqe) // 传递给链表的下一个
{
if (nextChain != nullptr)
{
nextChain->handler(rqe);
}
}
protected:
virtual void processRequest(const Request &req) = 0; // 处理,如何处理交给子类处理
virtual bool canHandleRequest(const Request &req) = 0; // 判断是否需要处理,交给子类来判断
public:
ChainHandler() { nextChain = nullptr; }
void setNextChain(ChainHandler *next) { nextChain = next; }
void handle(const Request &req)
{
if (canHandleRequest(req))
{
processRequest(req);
}
else
{
sendRequestToNExtHandler(req);
}
}
};
class Handler_1 : public ChainHandler{}; // 第一种处理
class Handler_2 : public ChainHandler{}; // 第二种处理
class Handler_3 : public ChainHandler{}; // 第三种处理
int main(){
Handler_1 h1;
Handler_2 h2;
Handler_3 h3;
h1.setNextChain(&h2);
h2.setNextChain(&h3);
Request req("open", RequestType::Open );
h1.handle(req);
return 0;
}
命令模式将请求行为封装成对象,从而使你可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作
class Command
{
public:
virtual void execute() = 0;
};
class ConcreteCommand_1 : public Command
{
std::string arg;
public:
virtual void execute() override
{
// 1号操作
}
};
class ConcreteCommand_2 : public Command
{
std::string arg;
public:
virtual void execute() override
{
// 2号操作
}
};
class MacroCommand : public Command // 组合操作
{
vector<Command *> commands;
public:
void addCommand(Command *c) { commands.push_back(c); }
void execute() override
{
for (auto &c : commands)
{
c->execute();
}
}
};