Boolan微专业-设计模式(Week02)
内容概要
本周主要介绍了“对象创建”和“接口隔离”两种类型的设计模式
对象创建
- Factory 工厂方法:绕开new,将对象创建的工作专门的交给一个工厂来完成,延迟实例化到子类
- Abstract Factory 抽象工厂:提供一个接口负责创建一些列相关对象
- Prototype 原型:使用Clone创建对象,用于结构复杂对象(需保留中间状态)的创建工作
- Builder 构建器:模板方法在对象创建中的应用---算法结构稳定,部分元素变化
接口隔离
- Facade 门面模式:解耦系统内与系统外对象间的关系
- Proxy 代理模式:由于性能、安全、分布式等原因,拆分两对象的直接访问关系,使用一个代理来转接
- Adapte 适配器:旧接口 --> 新接口
- Mediator 中介者:解耦系统内各对象间的关系
三、对象创建
通过“对象创建”模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。是接口抽象之后的第一步工作。
6.Factory Method 工厂方法
- 由于需求的变化,需要创建的对象的具体类型经常变化
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟(目的:解耦,手段:虚函数)到子类。 ———— 《设计模式》 GOF
- 工厂方法能够隐藏的类名,避免构造参数,避免在构造方法改变的时候能够避免修改每个new
-
工厂方法有什么用?
ISplitterFactor.h
//抽象类
class ISplitter {
public:
virtual void split() = 0;
virtual ~ISplitter() {}
};
//工厂基类
class SplitterFactory {
public:
virtual ISplitter* CreateSplitter() = 0;
virtual ~SplitterFactory() {}
};
FileSplitter.h
//具体类
class BinarySplitter : public ISplitter {};
class TxtSplitter : public ISplitter {};
class PictureSplitter : public ISplitter {};
class VideoSplitter : public ISplitter {};
//具体工厂
class BinarySplitterFactory : public SplitterFactory {
public:
virtual ISplitter* CreateSplitter() { return new BinarySplitter(); }
};
class TxtSplitterFactory : public SplitterFactory {
public:
virtual ISplitter* CreateSplitter() { return new TxtSplitter(); }
};
class PictureSplitterFactory : public SplitterFactory {
public:
virtual ISplitter* CreateSplitter() { return new PictureSplitter(); }
};
class VideoSplitterFactory : public SplitterFactory {
public:
virtual ISplitter* CreateSplitter() { return new VideoSplitter(); }
};
MainForm.cpp
class MainForm : public Form {
SplitterFactory* factory; //工厂
public:
MainForm(SplitterFactory* factory) { this->factory = factory; }
void Button1_Click() {
ISplitter* splitter = factory->CreateSplitter(); //多态new
splitter->split();
}
};
7.Abstract Factory 工厂方法
- 解决“一系列相互依赖的对象”的创建工作
提供一个接口,然该接口负责创建一系列“相关或者相互依赖的对象,无需指定它们具体的类。 ———— 《设计模式》 GOF
-
解决的是一系列相关对象的创建工作,这些对象之间往往是高耦合的,如各种数据库的连接、命令和读取器对象。
//数据库访问有关的基类
class IDBConnection {};
class IDBCommand {};
class IDataReader {};
class IDBFactory {
public:
virtual IDBConnection* CreateDBConnection() = 0;
virtual IDBCommand* CreateDBCommand() = 0;
virtual IDataReader* CreateDataReader() = 0;
};
//支持SQL Server
class SqlConnection : public IDBConnection {};
class SqlCommand : public IDBCommand {};
class SqlDataReader : public IDataReader {};
class SqlDBFactory : public IDBFactory {
public:
virtual IDBConnection* CreateDBConnection() {
//....
}
virtual IDBCommand* CreateDBCommand() {
//....
}
virtual IDataReader* CreateDataReader() {
//...
}
};
// 支持Oracle
// ....
class EmployeeDAO {
IDBFactory* dbFactory;
public:
vector<EmployeeDO> GetEmployees() {
IDBConnection* connection = dbFactory->CreateDBConnection();
connection->ConnectionString("...");
IDBCommand* command = dbFactory->CreateDBCommand();
command->CommandText("...");
command->SetConnection(connection); //关联性
IDBDataReader* reader = command->ExecuteReader(); //关联性
while (reader->Read()) {
}
}
};
8.Prototype 原型模式
- 解决“某些结构复杂的对象”的创建工作
使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。 ———— 《设计模式》 GOF
- 当一个对象的创建十分复杂(如构造函数的参数构造),又或者使用一个对象时对齐中间状态有要求,此时就可以使用原型模型,利用Clone来拷贝出一个供使用的副本。
-
Copy On Wirte 机制中也有类似用法,只用当需要写时,才拷贝出一份供使用者使用。
//抽象类
class ISplitter {
public:
virtual void split() = 0;
virtual ISplitter* clone() = 0; //通过克隆自己来创建对象
virtual ~ISplitter() {}
};
//具体类
class TxtSplitter : public ISplitter {
public:
virtual ISplitter* clone() { return new TxtSplitter(*this); }
};
class PictureSplitter : public ISplitter {
public:
virtual ISplitter* clone() { return new PictureSplitter(*this); }
};
// 客户端调用
class MainForm : public Form {
ISplitter* prototype; // 原型对象
public:
MainForm(ISplitter* prototype) { this->prototype = prototype; }
void Button1_Click() {
ISplitter* splitter = prototype->clone(); // 克隆原型
splitter->split(); // 不能直接使用原型对象,要先克隆,再使用其副本
}
};
9.Builder 构建器
- 解决构建算法稳定,子部分变化的对象的创建问题
将一个复杂对象的构建与其表示相分离,使得同样的构建过程(稳定)可以创建不同的表示(变化)。 ———— 《设计模式》 GOF
-
Template Method 模板方法在对象创建领域的应用
class House {
//....
};
class HouseBuilder {
public:
House* GetResult() { return pHouse; }
virtual ~HouseBuilder() {}
protected:
House* pHouse;
virtual void BuildPart1() = 0;
virtual void BuildPart2() = 0;
virtual void BuildPart3() = 0;
virtual void BuildPart4() = 0;
virtual void BuildPart5() = 0;
};
class StoneHouse : public House {};
class StoneHouseBuilder : public HouseBuilder {
protected:
virtual void BuildPart1() {
// pHouse->Part1 = ...;
}
virtual void BuildPart2() {}
virtual void BuildPart3() {}
virtual void BuildPart4() {}
virtual void BuildPart5() {}
};
class HouseDirector {
public:
HouseBuilder* pHouseBuilder;
HouseDirector(HouseBuilder* pHouseBuilder) {
this->pHouseBuilder = pHouseBuilder;
}
House* Construct() {
pHouseBuilder->BuildPart1();
for (int i = 0; i < 4; i++) {
pHouseBuilder->BuildPart2();
}
bool flag = pHouseBuilder->BuildPart3();
if (flag) {
pHouseBuilder->BuildPart4();
}
pHouseBuilder->BuildPart5();
return pHouseBuilder->GetResult();
}
};
四、接口隔离
添加一层间接(稳定)接口,来隔离本来互相紧密关联的接口。
10.Facade 门面模式
- 解耦系统内与系统外对象间的复杂关系
为子系统中的一组接口提供一个一致(稳定)的界面,Facade模式定义了一个高层接口,这个接口使得这一子系列更加容易使用(复用)。 ———— 《设计模式》 GOF。
-
Facade模式是从架构的层次去看待整个系统,是一种架构设计模式。对客户程序来说,其简化了整个组件系统的接口,达到了一种“解耦”的效果。如程序中的“数据访问层”
11.Proxy 代理模式
- 由于安全、性能、分布式等原因,有些对象直接创建使用的开销会很大。因此可增加一层间接层,提供一个代理进行转接。
为其他对象提供一种代理以控制(隔离,使用接口)对这个对象的访问。 ———— 《设计模式》 GOF
-
ClientApp直接使用Proxy进行访问,而对RealSubject的复杂返回逻辑则有Proxy负责,对用户透明。
class ISubject {
public:
virtual void process();
};
// Proxy的设计
class SubjectProxy : public ISubject {
public:
virtual void process() {
//对RealSubject的一种间接访问
//....
}
};
class ClientApp {
ISubject* subject;
public:
ClientApp() { subject = new SubjectProxy(); }
void DoTask() {
//...
subject->process();
//....
}
};
12.Adapter 适配器
- 将“一些现存的对象”放在新的环境中使用,旧接口 --> 新接口
将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 ———— 《设计模式》 GOF
-
利用继承"IS-A"和组合"HAS-A"的方式完成旧接口向新接口的转换工作。其重点是一种思想,不必拘泥结构,如STL重点Stack和Queue就是利用Deque实现的
//目标接口(新接口)
class ITarget {
public:
virtual void process() = 0;
};
//遗留接口(老接口)
class IAdaptee {
public:
virtual void foo(int data) = 0;
virtual int bar() = 0;
};
//遗留类型
class OldClass : public IAdaptee {
//....
};
//对象适配器
class Adapter : public ITarget { //继承
protected:
IAdaptee* pAdaptee; //组合
public:
Adapter(IAdaptee* pAdaptee) { this->pAdaptee = pAdaptee; }
virtual void process() {
int data = pAdaptee->bar();
pAdaptee->foo(data);
}
};
/*
类适配器(不推荐使用,不够灵活)
class Adapter : public ITarget, protected OldClass { //多继承
}
*/
int main() {
IAdaptee* pAdaptee = new OldClass();
ITarget* pTarget = new Adapter(pAdaptee);
pTarget->process();
}
13.Mediator 中介者
- 解决对个对象互相关联交互的情况,是对系统内各对象间复杂关系的解耦
用一个中介对象来封装(封装变化)一系列的对象交互。中介者使各对象不需要显示的相互引用(编译时依赖 ——> 运行时依赖),从而使其耦合松散(管理变化),而且可以独立地改变它们之间的交互。 ———— 《设计模式》 GOF
-
Facade模式是解耦系统间(单向)的对象关联关系,Mediator模式是解耦系统内各个对象之间(双向)的关联关系。其也是一种架构思想。