前言
结构模式可以让我们把很多小的东西通过结构模式组合起来成为一个打的结构,但是又不影响各自的独立性,尽可能减少各组件之间的耦合。
Adapter Class/Object(适配器)
GOOD:双方都不适合修改的时候,可以考虑使用适配器模式,一般发生在代码的维护阶段。
adapter.h
cpp
#ifndef CLION_TEST_ADAPTER_H
#define CLION_TEST_ADAPTER_H
#include <iostream>
#include <string>
#include <utility>
using namespace std;
// 球员
class Player {
protected:
string name;
public:
explicit Player(string strName) { name = std::move(strName); }
virtual void Attack() = 0;
virtual void Defense() = 0;
};
// 前锋
class Forwards : public Player {
public:
explicit Forwards(string strName) : Player(std::move(strName)) {}
void Attack() final {
cout << name << "前锋进攻" << endl;
}
void Defense() final {
cout << name << "前锋防守" << endl;
}
};
// 中锋
class Center : public Player {
public:
explicit Center(string strName) : Player(std::move(strName)) {}
void Attack() final {
cout << name << "中场进攻" << endl;
}
void Defense() final {
cout << name << "中场防守" << endl;
}
};
// 后卫
class Guards : public Player {
public:
Guards(string name) : Player(name) {}
void Attack() final {
cout << name << "后卫进攻" << endl;
}
void Defense() final {
cout << name << "后卫防守" << endl;
}
};
// Adaptee,此处为外籍中锋,它的接口和Target的接口不一样,需要翻译来帮忙转换
class ForeignPlayerCenter {
private:
string name;
public:
void setName(string name) {
this->name = name;
}
string getName() const { return name; }
void ForeignAttack() {
cout << name << "外籍中锋进攻" << endl;
}
void ForeignDefense() {
cout << name << "外籍中锋防守" << endl;
}
};
// 为中场翻译
class TransLater : public Player {
private:
ForeignPlayerCenter *wjzf;
public:
explicit TransLater(const string &strName) : Player(strName) {
wjzf = new ForeignPlayerCenter;
wjzf->setName(name);
}
~TransLater() {
delete wjzf;
}
void Attack() {
wjzf->ForeignAttack();
}
void Defense() {
wjzf->ForeignDefense();
}
};
#endif //CLION_TEST_ADAPTER_H
main.cpp
cpp
int main()
{
system("chcp 65001");
Player *b = new Forwards("巴蒂尔");
b->Attack();
Player *m = new Guards("麦克格雷迪");;
m->Attack();
// 翻译告诉姚明,教练让你既要进攻,又有防守
Player* ym = new TransLater("姚明");
ym->Attack();
ym->Defense();
return 0;
}
Bridge(桥接)
Composite(组合)
Decorator(装饰)
动态地给一个对象添加一些额外的职责(不重要的功能,只是偶然一次要执行),就增加功能来说,装饰模式比生成子类更为灵活。 建造过程不稳定,按正确的顺序串联起来进行控制。
GOOD:当你向旧的类中添加新代码时,一般是为了添加核心职责或主要行为。而当需要加入的仅仅是一些特定情况下才会执行的特定的功能时(简单点就是不是核心应用的功能),就会增加类的复杂度。装饰模式就是把要添加的附加功能分别放在单独的类中,并让这个类包含它要装饰的对象,当需要执行时,客户端就可以有选择地、按顺序地使用装饰功能包装对象。
decorator.h
cpp
#ifndef CLION_TEST_DECORATOR_H
#define CLION_TEST_DECORATOR_H
#include <string>
#include <iostream>
using namespace std;
// 人
class Person
{
private:
string m_strName;
public:
Person(string strName) {
m_strName = strName;
}
Person() {}
virtual void Show()
{
cout<<"装扮的是:"<<m_strName<<endl;
}
};
// 装饰类
class Finery:public Person
{
protected:
Person* m_component;
public:
void Decorate(Person* component) {
m_component = component;
}
void Show() override
{
m_component->Show();
}
};
// T恤
class TShirts:public Finery
{
public:
void Show() final
{
cout<<"T Shirts ";
m_component->Show();
}
};
// 裤子
class BigTrouer: public Finery
{
void Show() final
{
cout<<"Big Trouer ";
m_component->Show();
}
};
#endif //CLION_TEST_DECORATOR_H
main.cpp
cpp
#include <iostream>
#include "decorator.h"
using namespace std;
int main() {
system("chcp 65001");
// 装饰模式
Person *p = new Person("小李");
BigTrouer *bt = new BigTrouer();
TShirts *ts = new TShirts();
bt->Decorate(p);
ts->Decorate(bt);
ts->Show();
return 0;
}
输出:
T Shirts Big Trouer 装扮的是:小李
调用关系:
cpp
TShirts::Show ==> BigTrouer::Show ==> Person::Show
Facade(外观)
GOOD:为子系统的一组接口提供一个一致的界面。使用户使用起来更加方便。
facade.h
cpp
#ifndef CLION_TEST_FACADE_H
#define CLION_TEST_FACADE_H
#include <iostream>
using namespace std;
class Stock1 {
public:
void Buy() {
cout << "股票1买入" << endl;
}
void Sell() {
cout << "股票1卖出" << endl;
}
};
class Stock2 {
public:
void Buy() {
cout << "股票2买入" << endl;
}
void Sell() {
cout << "股票2卖出" << endl;
}
};
class Stock3 {
public:
void Buy() {
cout << "股票3买入" << endl;
}
void Sell() {
cout << "股票3卖出" << endl;
}
};
// 基金类
class Fund {
private:
Stock1 *gu1;
Stock2 *gu2;
Stock3 *gu3;
public:
Fund() {
gu1 = new Stock1();
gu2 = new Stock2();
gu3 = new Stock3();
}
void BuyFund() {
gu1->Buy();
gu2->Buy();
gu3->Buy();
}
void SellFund() {
gu1->Sell();
gu2->Sell();
gu3->Sell();
}
};
#endif //CLION_TEST_FACADE_H
main.cpp
cpp
#include "facade.h"
using namespace std;
int main() {
system("chcp 65001");
// 外观模式
Fund* jijin = new Fund();
// 基金购买
jijin->BuyFund();
// 基金赎回
jijin->SellFund();
return 0;
}
使用外观模式的三个场景:
1、在设计初期阶段,应该要有意识的将不同的两个层分离,层与层之间建立外观Facade。
2、在开发阶段。子系统往往因为不断的重构演化而变得越来越复杂,增加外观Facade可以提供一个简单的接口,减少它们之间的依赖。
3、在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,为新系统开发一个外观Facade类,来提供涉及粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作。
Flyweight(享元)
Proxy(代理)
GOOD:远程代理,可以隐藏一个对象在不同地址空间的事实
虚拟代理:通过代理来存放需要很长时间实例化的对象
安全代理:用来控制真实对象的访问权限
智能引用:当调用真实对象时,代理处理另外一些事
proxy.h
cpp
#ifndef CLION_TEST_PROXY_H
#define CLION_TEST_PROXY_H
#include <string>
#include <iostream>
using namespace std;
// 定义接口
class Interface {
public:
virtual void Request() = 0;
};
// 真实类
class RealClass : public Interface {
public:
void Request() final {
cout << "真实的请求" << endl;
}
};
// 代理类
class ProxyClass : public Interface {
private:
RealClass *m_realClass;
public:
void Request() final {
if (m_realClass == nullptr) {
m_realClass = new RealClass();
}
m_realClass->Request();
}
};
#endif //CLION_TEST_PROXY_H
main.cpp
cpp
int main() {
ProxyClass* test = new ProxyClass();
test->Request();
return 0;
}
调用关系:
cpp
ProxyClass::Request ==> RealClass::Request