文章目录
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者采用组合或聚合组合对象。由于组合关系或聚合关系比较继承关系耦合度低,满足“合成复合原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。
1.代理模式
Proxy模式又被叫做代理模式,是结构型的设计模式之一,它可以为其他对象提供一种代理以控制对这个对象的访问。
subject(抽象主题角色):真实主题与代理主题的共同接口。
RealSubject(真实主题角色):定义了代理角色所代表的真实对象。
Proxy(代理主题角色):含有对真实主题角色的引用,代理角色通常在将客户端调用传递给真实主题对象之前或者之后执行某些操作,而不是单纯返回真实的对象。
#include <iostream>
#include <string>
using namespace std;
// 物品
class Item
{
public:
Item(string kind,bool fake)
{
this->kind = kind;
this->fake = fake;
}
// 物品类别
string kind;
// true:假货,false:真货
bool fake;
};
// subject(抽象主题角色),抽象的购物方式,具有买的功能
class Shopping
{
public:
virtual void buy(Item& item) = 0;
};
// RealSubject(真实主题角色),去韩国购物
class KoreaShopping : public Shopping
{
public:
virtual void buy(Item& item)
{
cout << "去韩国购物,买了" << item.kind << endl;
}
};
// RealSubject(真实主题角色),去美国购物
class USAShopping : public Shopping
{
public:
virtual void buy(Item& item)
{
cout << "去美国购物,买了" << item.kind << endl;
}
};
// RealSubject(真实主题角色),去非洲购物
class AfricaShopping : public Shopping
{
public:
virtual void buy(Item& item)
{
cout << "去非洲购物,买了" << item.kind << endl;
}
};
// Proxy(代理主题角色),海外代购 代理,实现了购物模式,而且还增加了辨别货物真伪和海关安检具体业务。
class OverseasProxy : public Shopping
{
public:
OverseasProxy(Shopping* shopping)
{
this->shopping = shopping;
}
~OverseasProxy()
{
delete this->shopping;
}
bool distinguish(Item& item)
{
cout << "对物品[" << item.kind << "]辨别真伪." << endl;
return item.fake;
}
void check(Item& item)
{
cout << "通过海关安检,带回国内" << endl;
}
virtual void buy(Item& item)
{
if(distinguish(item) == false)
{
this->shopping->buy(item);
check(item);
}
else
{
cout << "发现伪货[" << item.kind << "],不能购买" << endl;
}
}
private:
Shopping* shopping;
};
int main(void)
{
Item item1("化妆品",false);
Item item2("学位证",true);
Item item3("空调",false);
Shopping* shopping = NULL;
OverseasProxy* proxy = NULL;
// 1.去韩国买化妆品
proxy = new OverseasProxy(new KoreaShopping);
proxy->buy(item1);
delete proxy;
// 2.去美国买学位证
proxy = new OverseasProxy(new USAShopping);
proxy->buy(item2);
delete proxy;
// 3.去非洲买空调
proxy = new OverseasProxy(new AfricaShopping);
proxy->buy(item3);
delete proxy;
return 0;
}
2.适配器(Adapter)模式
在软件设计中也可能出现:需要开发的具有某种业务功能的组件在现有的组件库中已经存在,但它们与当前系统的接口规范不兼容,如果重写开发这些组件成本又很高,这时用是适配器模式能很好地解决这些问题。适配器模式的定义如下:将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起功能的那些类能一起工作。适配器模式分为类结构型模式和对象结构型模式两种,前者之间的耦合度比后者高,其要求程序员了解现有组件库中的相关的内部结构,所以应对相对较少些。
Target(目标抽象类):目标抽象类,定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。
Adaptee(适配者类):适配者即被适配的角色,它 定义了一个已经存在的接口,这个接口需要适配,适配者类 一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。
Adapter(适配器类):适配器可以调用另一个接口,作为一个转换器,对 Adaptee 和 Target 进行适配,适配器类是适配器模式的核心,在对象适配器中,它通过继承Target并关联一个Adaptee对象使二者产生联系 。
#include <iostream>
using namespace std;
// Target(目标抽象类),5V 电压
class V5
{
public:
virtual void useV5() = 0;
};
// Adaptee(适配者类),220V 电压
class V220
{
public:
virtual void useV220()
{
cout << "用 220V 电压进行充电" << endl;
}
};
// Adapter(适配器类),手机充电器
class PhoneChargeAdapter : public V5
{
public:
virtual void useV5()
{
cout << "手机充电器对电压进行适配" << endl;
m_v220.useV220();
}
private:
V220 m_v220;
};
class Phone
{
public:
Phone()
{
v5 = new PhoneChargeAdapter;
}
~Phone()
{
if(v5 != NULL)
delete v5;
}
void charge()
{
cout << "手机进行充电" << endl;
v5->useV5();
}
private:
V5* v5;
};
int main(void)
{
Phone iphone;
iphone.charge();
return 0;
}
3.桥接模式
将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。
//OS.h
#ifndef OS_H_
#define OS_H_
#include <iostream>
using namespace std;
//抽象的操作系统类
class OS
{
public:
virtual std::string GetOS() = 0;
};
//IOS类的实现
class IOS : public OS
{
public:
virtual std::string GetOS()
{
return "IOS Operator System";
}
};
//塞班类的实现
class SaiBian : public OS
{
public:
virtual std::string GetOS()
{
return "SaiBian Operator System";
}
};
//IOS某个版本的实现
class IOSSubSystem1 : public IOS
{
public:
virtual std::string GetOS()
{
return "IOS 5.1.1 Operator System";
}
};
//IOS某个版本的实现
class IOSSubSystem2 : public IOS
{
public:
virtual std::string GetOS()
{
return "IOS 10.1.1 Operator System";
}
};
//塞班系统某个类的实现
class SaiBianSubSystem1 : public SaiBian
{
public:
virtual std::string GetOS()
{
return "SaiBian 1.1.0 Operator System";
}
};
//塞班系统某个类的实现
class SaiBianSubSystem2 : public SaiBian
{
public:
virtual std::string GetOS()
{
return "SaiBian 1.1.1 Operator System";
}
};
#endif
//phone.h
#ifndef PHONE_H_
#define PHONE_H_
#include "OS.h"
#ifndef DELETE_OBJECT
#define DELETE_OBJECT(p) {if(NULL != (p)){delete (p); (p) = NULL;}}
#endif
//抽象的手机类
class Phone
{
public:
virtual void SetOS() = 0;
};
//苹果手机类,依赖抽象的操作系统
class iPhone : public Phone
{
public:
iPhone(OS* os)
{
m_pOS = os;
}
~iPhone()
{
DELETE_OBJECT(m_pOS);
}
virtual void SetOS()
{
cout << "Set The OS: " << m_pOS->GetOS().c_str() << endl;
}
private:
OS* m_pOS;
};
//诺基亚手机类,以来抽象的操作系统
class Nokia : public Phone
{
public:
Nokia(OS* os)
{
m_pOS = os;
}
~Nokia()
{
DELETE_OBJECT(m_pOS);
}
virtual void SetOS()
{
cout << "Set The OS: " << m_pOS->GetOS().c_str() << endl;
}
private:
OS* m_pOS;
};
#endif
//client
#include <iostream>
#include "OS.h"
#include "Phone.h"
using namespace std;
#ifndef DELETE_OBJECT
#define DELETE_OBJECT(p) {if(NULL != (p)){delete (p); (p) = NULL;}}
#endif
int main()
{
OS* pIOS1 = new IOSSubSystem1(); //创建一个操作系统
Phone* iPhone4 = new iPhone(pIOS1);//应用到该手机上
iPhone4->SetOS();
OS* pIOS2 = new IOSSubSystem2();//创建一个操作系统
Phone* iPhone6 = new iPhone(pIOS2);//应用到该手机上
iPhone6->SetOS();
OS* pSaiBian1 = new SaiBianSubSystem1();//创建一个操作系统
Phone* Nokia1 = new Nokia(pSaiBian1);//应用到该手机上
Nokia1->SetOS();
OS* pSaiBian2 = new SaiBianSubSystem2();//创建一个操作系统
Phone* Nokia2 = new Nokia(pSaiBian2);//应用到该手机上
Nokia2->SetOS();
DELETE_OBJECT(iPhone4);
DELETE_OBJECT(iPhone6);
DELETE_OBJECT(Nokia1);
DELETE_OBJECT(Nokia2);
return 0;
}
优点:将抽象与实现分离,提高了系统的可扩展性。不管是在两个维度还是更高维度上变化,都只需要在各自维度的变化上修改即可,不需要修改原有系统。
缺点:维度变化过多过杂,很难将单纯变化的两个维度分离开来。在设计上有一定难度。
合理的脚本代码可以有效的提高工作效率,减少重复劳动。
4.作者答疑
如有疑问,请留言。