设计模式究竟是什么?其实设计模式也就是一些写代码的方式,主要是针对面向对象的。设计模式通常应用在设计阶段,分析阶段已经对系统分层,然后也对每个层都提取了一些类。这个时候,如何组织和使用这些类就是我们的设计模式要研究的问题了。
对于我们程序员来说,千言万语抵不过一句简单的代码。下面让我们看看实现一些设计模式的代码:
/
Adapter模式:
#include <stdio.h>
// 已存在的类,将要被适配者
class XCircle
{
public:
XCircle()
{
printf("我是XCircle/n");
}
void DisplayIT()
{
printf("显示一个圆/n");
}
};
class CShape
{
public:
virtual void Display() = 0;
};
// 因为XCircle已经实现了显示圆的操作,所以我们不用重新实现了,拿来用一下
class CCircle : public CShape
{
public:
CCircle()
{
printf("我是CCircle/n");
}
virtual void Display()
{
printf("CCircle借用一下XCircle的显示操作:/n");
_xc.DisplayIT();
}
private:
XCircle _xc;
};
int main()
{
CCircle circle;
circle.Display();
return 0;
}
/
Builder模式:
/**********************************************************************************************************************/
* Builder模式:
* 我们可以将Builder理解成电饭锅,给这个Builder放进去米和水,经过Builder的Build后,我们就可以取出香喷喷的米饭了。
* 意图: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
* 适用性: 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
* 当构造过程必须允许被构造的对象有不同的表示时。
/**********************************************************************************************************************/
#include <stdio.h>
#include <string>
// 汽车类,要制作一部车,工程大吧?所以使用BUILDER模式将对象的建造分开。
class CCar
{
public:
void What()
{
printf("%s", szWhat);
}
void Drive()
{
printf("开车咯!/n");
}
char szWhat[100];
};
// 车的Builder
class CCarBuilder
{
public:
virtual void BuildCar() = 0;
virtual CCar* GetResult() = 0;
protected:
CCarBuider();
};
class CBenchBuilder : public CCarBuilder
{
public:
CBenchBuilder()
{
_car = NULL;
}
virtual void BuildCar()
{
if(_car == NULL)
_car = new CCar;
strcpy(_car->szWhat, "我是奔驰车!");
};
virtual CCar* GetResult(){return _car;}
private:
CCar *_car;
};
/**********************************************************************************************************************/
* 我想开不同的车,只要传个不同的建造者进去就行了。
/**********************************************************************************************************************/
void Drive(CCarBuilder &builder)
{
CCar *car;
builder.BuildCar();
car = builder.GetResult();
car->What();
car->Drive();
}
void main()
{
CBenchBuilder builder;
Drive(builder);
}
Factory模式:
#include <stdio.h>
class CFruit
{
public:
virtual void What() = 0;
};
class CApple : public CFruit
{
public:
virtual void What()
{
printf("我是一个苹果/n");
}
};
class CPear : public CFruit
{
public:
virtual void What()
{
printf("我是一只雪梨/n");
}
};
class CBanana : public CFruit
{
public:
virtual void What()
{
printf("我是一条香蕉/n");
}
};
enum eFruitType{APPLE=1, PEAR, BANANA};
class CFruitFactory
{
public:
CFruit *GetFruitInstance(eFruitType type)
{
printf("工厂正在生产水果.../n");
switch(type)
{
case APPLE:
return new CApple();
case PEAR:
return new CPear();
case BANANA:
return new CBanana();
default:
return NULL;
}
}
};
int main()
{
CFruitFactory factory;
CFruit *fruit;
printf("你想吃什么水果?/n");
printf("1 苹果, 2 雪梨, 3 香蕉/n");
int nType = 0;
scanf("%d", &nType);
fruit = factory.GetFruitInstance(eFruitType(nType));
if(fruit == NULL)
{
printf("没有这种水果。");
return 0;
}
fruit->What();
return 0;
}
Observer模式:
/**********************************************************************************************************************/
* 观察者模式
* [说明]
* 在一公文处理系统中,开发者定义了一个公文类OfficeDoc, 其中定义了公文具有的属性和处理公文的相应方法。当公文件的内容或
* 状态发生变化时,关注此OfficeDoc 类对象的相应的DocExplorer 对象都要更新其自身的状态。一个OfficeDoc 对象能够关联一组
* DocExplorer 对象。当OfficeDoc 对象的内容或状态发生变化时,所有与之相关联的DocExplorer对象都将得到通知,这种应用被称
* 为观察者模式。
*
* 例如MFC的DOC、VIEW架构都是基于这种观察者的模式。
/**********************************************************************************************************************/
/**********************************************************************************************************************/
* 本代码还用了一种标示的方法实现了在运行时辨识对象。
* RTTI只能在运行时实现类型的识别。没法实现对象的识别。
/**********************************************************************************************************************/
#include <stdio.h>
#include <typeinfo>
// 最多与OfficeDoc关联的DocExplorer对象的个数
const int OBS_MAX = 20;
class COfficeDoc;
// 关注OfficeDoc公文对象的类
class CDocExplorer
{
public:
CDocExplorer(COfficeDoc *doc);
void UpdateSelf(COfficeDoc *doc);
// 为了实现对象的识别,在此加一个标示
int nExplorerID;
};
class COfficeDoc
{
public:
COfficeDoc()
{
index = 0;
}
void Attach(CDocExplorer *e)
{
if(index >= OBS_MAX || e == NULL)
{
return;
}
myObs[index] = e;
index++;
e->nExplorerID = index;
}
void Detach(CDocExplorer *e)
{
for(int i = 0; i <index; i++)
{
if(myObs[i] == e)
{
// 把当前位置的观察者对象和最后一个对象交换,并把index的值减一个
if(i <= index-2)
myObs[i] = myObs[index-1];
myObs[index - 1] = NULL;
index--;
break;
}
}
}
// 修改数据,并通知观察者更新
void ModifyData(int data)
{
printf("公文的数据改变成:%d/n", data);
m_nData = data;
NotifyObs();
}
private:
CDocExplorer *myObs[OBS_MAX]; // 观察者的类对象指针数组
int index;
// 通知所有的观察者对象改变自己的状态
void NotifyObs()
{
for(int i = 0; i < index; i++)
{
myObs[i]->UpdateSelf(this);
}
}
public:
// 公文的数据
int m_nData;
};
CDocExplorer::CDocExplorer(COfficeDoc *doc)
{
doc->Attach(this);
}
void CDocExplorer::UpdateSelf(COfficeDoc *doc)
{
// 把下面两行的注释打开还可以看到typeid和type_info的用法
// 会发现typeid只能实现类型的识别
//const type_info &t = typeid(*doc);
//printf("我正在观察%s/n", t.name());
printf("我是观察者%d, ", nExplorerID);
printf("更新数据: %d /n", doc->m_nData);
}
int main()
{
COfficeDoc officeDoc;
CDocExplorer docExplorer0(&officeDoc);
CDocExplorer docExplorer1(&officeDoc);
CDocExplorer docExplorer2(&officeDoc);
CDocExplorer docExplorer3(&officeDoc);
CDocExplorer docExplorer4(&officeDoc);
// 更新公文的数据
officeDoc.ModifyData(123);
printf("/n");
officeDoc.ModifyData(567);
return 0;
}
Singleton模式:
/**********************************************************************************************************************************************/
* [说明]
* 通常情况下,用户可以对应用系统进行配置,并将配置信息保存在配置文件中,应用系统在启动时首先将配置文件加载到内存中,
* 这些内存配置信息应该有且仅有一份。
* 下面的代码应用了单身模式(Singleton)以保证Configure类只能有一个实例。这样,Configure类的使用者无法定义该类的多个实例,
* 否则会产生编译错误。
/**********************************************************************************************************************************************/
#include "stdio.h"
#include <assert.h>
class CConfigFile
{
private:
CConfigFile(){}
public:
static CConfigFile* Instance();
void GetConfigData(int &data);
void SetConfigData(int data);
private:
static CConfigFile* _instance;
int _data;
};
// 注意:静态变量的初始化格式
CConfigFile* CConfigFile::_instance = NULL;
void CConfigFile::SetConfigData(int data)
{
_data = data;
}
void CConfigFile::GetConfigData(int &data)
{
data = _data;
}
CConfigFile* CConfigFile::Instance()
{
if(_instance == NULL)
{
_instance = new CConfigFile();
// 加载配置文件并设置内存配置信息,此处省略
}
return _instance;
}
int main(int argc, char* argv[])
{
CConfigFile *configFile = NULL;
configFile = CConfigFile::Instance();
configFile->SetConfigData(3);
int tmp = 0;
configFile->GetConfigData(tmp);
// 获取配置信息后进行其它工作,此处省略
assert(tmp == 3);
return 0;
}