设计模式——结构型模式

news/2024/11/29 8:34:52/

前言

本文只是记录本人学习设计模式时记录的一些学习笔记,可能不全,但是可以做到一些提醒记忆的作用,如有侵权,联系删改,文章后会贴出学习时参考的链接。此前言适用于本人所写设计模式系列。

结构型模式

​ 描述的是如何组合类和对象以获得更大的结构

7. 代理(Proxy)

为其他对象提供一种代理以控制对这个对象的访问

结构:

  1. subject(抽象主题角色):
    ​ 真实主题与代理主题的共同接口。
  2. Real Subject(真实主题角色):
    定义了代理角色所代表的真实对象。
  3. Proxy(代理主题角色):
    含有对真实主题角色的引用,代理角色通常在将客户端调用传递给真是主题对象之前或者之后执行某些操作,而不是单纯返回真实的对象。

示例:

class AbstractCommonInterface{virtual void run() = 0;
};class MySystem : public AbstractCommonInterface{
public:virtual void run(){cout << "system start..." << endl;}virtual ~MySystem(){}
};class MySystemProxy : public AbstractCommonInterface{
public:MySystemProxy(string username, string password){this->mUsername = username;this->mPassword = password;pSystem = new MySystem;}bool checkUsernameAndPassword(){if(mUsername == "admin" && mPassword == "admin"){return true;}return false;}virtual void run(){if(checkUsernameAndPassword()){cout << "success" << endl;this->pSystem->run();}else {cout << "error" << endl;}}~MySystemProxy(){if(pSystem != NULL){delete pSystem;}}
public:MySystem* pSystem;string mUsername;string mPassword;
};

8. 装饰(Decorator )

通过一种对客户端透明的方式来扩展对象功能,是继承关系的一种替代

示例:

  1. 创建一个抽象类英雄
  2. 创建一个具体英雄A,继承于抽象英雄
  3. 创建装饰装备,继承于抽象英雄,使用时,传入被装饰的英雄A,返回穿上装备的英雄A
  4. 需要装饰什么样的装备,即创建什么样的装备类即可
class AbstractHero{
public:virtual void ShowStatus() = 0;virtual ~AbstractHero(){}
public:int mHp;int mMp;int mAt;int mDf;
};
class HeroA : public AbstractHero{
public:HeroA(){mHp = 0;mMp = 0;mAt = 0;mDf = 0;}virtual void ShowStatus(){cout << "血量:" << mHp << endl;cout << "魔法:" << mMp << endl;cout << "攻击:" << mAt << endl;cout << "防御:" << mDf << endl;}
};
class AbstractEquipment : public AbstractHero{
public:AbstractEquipment(AbstractHero* hero){this->pHero = hero;}virtual void ShowStatus(){}
public:AbstractHero* pHero;
};
class KuangtuEquipment : public AbstractEquipment{
public:KuangtuEquipment(AbstractHero* hero) :AbstractEquipment(hero){}void AddKuangtu(){cout << "英雄穿上狂徒……" << endl;this->mHp = this->pHero->mHp;this->mMp = this->pHero->mMp;this->mAt = this->pHero->mAt;this->mDf = this->pHero->mDf + 30;delete this->pHero;}virtual void ShowStatus(){AddKuangtu();cout << "血量:" << mHp << endl;cout << "魔法:" << mMp << endl;cout << "攻击:" << mAt << endl;cout << "防御:" << mDf << endl;}
};
class WUjinKnife : public AbstractEquipment{
public:WUjinKnife(AbstractHero* hero) :AbstractEquipment(hero){}void AddWUjinKnife(){cout << "英雄穿上无尽之刃……" << endl;this->mHp = this->pHero->mHp;this->mMp = this->pHero->mMp;this->mAt = this->pHero->mAt + 80;this->mDf = this->pHero->mDf;delete this->pHero;}virtual void ShowStatus(){AddWUjinKnife();cout << "血量:" << mHp << endl;cout << "魔法:" << mMp << endl;cout << "攻击:" << mAt << endl;cout << "防御:" << mDf << endl;}
};

9. 外观(Facade)

将复杂的子类系统抽象到同一个的接口进行管理

结构:

  1. Facade
    为调用方, 定义简单的调用接口。
  2. Clients
    调用者。通过Facade接口调用提供某功能的内部类群。
  3. Packages
    功能提供者。指提供功能的类群(模块或子系统)

示例:

为子系统中统一一套接口,让子系统更加容易使用

class TV{
public:void On(){cout << "TV On..." << endl;}void Off(){cout << "TV Off..." << endl;}
};
class Light{
public:void On(){cout << "Light On..." << endl;}void Off(){cout << "Light Off..." << endl;}
};
class Audio{
public:void On(){cout << "Audio On..." << endl;}void Off(){cout << "Audio Off..." << endl;}
};
class Microphone{
public:void On(){cout << "Microphone On..." << endl;}void Off(){cout << "Microphone Off..." << endl;}
};
class DVDPlayer{
public:void On(){cout << "DVDPlayer On..." << endl;}void Off(){cout << "DVDPlayer Off..." << endl;}
};
class Gamemachine{
public:void On(){cout << "Gamemachine On..." << endl;}void Off(){cout << "Gamemachine Off..." << endl;}
};
class KTVMode{
public:KTVMode(){pTV = new TV;pLight = new Light;pAudio = new Audio;pMicrophone= new Microphone;pDvd = new DVDPlayer;}void OnKtv(){pTV->On();pLight->Off();pAudio->On();pMicrophone->On();pDvd->On();}void OffKtv(){pTV->Off();pLight->On();pAudio->Off();pMicrophone->Off();pDvd->Off();}~KTVMode(){delete pTV;delete pLight;delete pAudio;delete pMicrophone;delete pDvd;}
public:TV* pTV;Light* pLight;Audio* pAudio;Microphone* pMicrophone;DVDPlayer* pDvd;
};class GameMode{
//
};

10. 适配器(Adapter)

将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作

示例:

MyPrint接口需要v1,v2两个参数,for_each只返回一个参数,即需要将MyPrint适配成for_each能够使用.

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct MyPrint
{void operator()(int v1,int v2){cout << v1 + v2 << endl;}
};
class Target
{
public:virtual void operator()(int v) = 0;
};
class Adapter : public Target
{
public:Adapter(int param){this->param = param;}virtual void operator()(int v){print(v,param);}
public:MyPrint print;int param;
};
int main()
{vector<int> v;for(int i = 0; i < 10; i++){v.push_back(i);}for_each(v.begin(), v.end(),Adapter(10));return 0;
}

11. 桥接(Bridge )

将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

结构:

  1. Client
    Bridge模式的使用者
  2. Abstraction
    抽象类接口(接口或抽象类)维护对行为实现(Implementor)的引用
  3. Refined Abstraction
    Abstraction子类
  4. Implementor
    行为实现类接口 (Abstraction接口定义了基于Implementor接口的更高层次的操作)
  5. Concrete Implementor
    Implementor子类

示例:

class Engine
{
public:virtual void InstallEngine() = 0;};
class E4400cc : public Engine
{
public:virtual void InstallEngine(){cout << "4400cc 安装完毕" << endl;}
};class E4500cc : public Engine
{
public:virtual void InstallEngine(){cout << "4500cc 安装完毕" << endl;}
};class Car
{
public:Car(Engine *engine){this->m_engine = engine;}virtual void installEngine() = 0;
protected:Engine *m_engine;
};class BMW5 : public Car
{
public:BMW5(Engine *engine) : Car(engine){}virtual void installEngine(){cout << "BWM5"<< endl;m_engine->InstallEngine();}
};class BMW8 : public Car
{
public:BMW8(Engine *engine) : Car(engine){}virtual void installEngine(){m_engine->InstallEngine();}
};

12. 组合(Composite)

通过递归手段来构造树形的对象结构,并可以通过一个对象来访问整个对象树。

结构:

  1. Component (树形结构的节点抽象)
    - 为所有的对象定义统一的接口(公共属性,行为等的定义)
    - 提供管理子节点对象的接口方法
    - [可选]提供管理父节点对象的接口方法
  2. Leaf (树形结构的叶节点)
  3. Component的实现子类
  4. Composite(树形结构的枝节点)
  5. Component的实现子类

示例:

class IFile
{
public:virtual void display() = 0;virtual int add(IFile *ifile) = 0;virtual int remove(IFile *ifile) = 0;virtual list<IFile *>* getChild() = 0;
};
class File : public IFile
{
public:File(string name){this->m_name = name;}virtual void display(){cout << m_name << endl;}virtual int add(IFile *ifile){return -1;}virtual int remove(IFile *ifile){return -1;}virtual list<IFile *>* getChild(){return NULL;}
private:string m_name;
};class Dir : public IFile
{
public:Dir(string name){this->m_name = name;m_list = new list<IFile *>;m_list->clear();}virtual void display(){cout << m_name << endl;}virtual int add(IFile *ifile){m_list->push_back(ifile);return 0;}virtual int remove(IFile *ifile){m_list->remove(ifile);return 0;}virtual list<IFile *>* getChild(){return m_list;}
private:string m_name;list<IFile *> *m_list;
};void showTree(IFile *dir, int lever)
{dir->display();list<IFile *> *mylist = dir->getChild();if(mylist != NULL){for(list<IFile *>::iterator it = mylist->begin(); it != mylist->end(); it++){for(int i = 0; i <= lever; i++){cout << "\t";}if((*it)->getChild() != NULL){cout << "==>";showTree(*it, lever+1);}else{(*it)->display();}}}
}

13. 享元(Flyweight)

通过与其他类似对象共享数据来减少内存占用

结构:

  1. 抽象享元角色:
    所有具体享元类的父类,规定一些需要实现的公共接口。
  2. 具体享元角色:
    抽象享元角色的具体实现类,并实现了抽象享元角色规定的方法。
  3. 享元工厂角色:
    负责创建和管理享元角色。

示例:

class Person
{
public:Person(string name, int age){this->m_name = name;this->m_age = age;}virtual ~Person(){}virtual void printT() = 0;
protected:string m_name;int m_age;
};
class Teacher : public Person
{
public:Teacher(string name, int age, string id):Person(name, age){this->m_id = id;}void printT(){cout << "name:" << m_name << "\tage:" << m_age << "\tid:" << m_id << endl;}
private:string m_id;
};
class FlyWeightTeacherFactory
{
public:FlyWeightTeacherFactory(){map1.clear();}~FlyWeightTeacherFactory(){while (!map1.empty()) {Person *tmp = NULL;map<string, Person*>::iterator it= map1.begin();tmp = it->second;map1.erase(it);delete tmp;}}Person* GetTeacher(string id){Person *tmp = NULL;map<string, Person*>::iterator it;it = map1.find(id);if(it == map1.end()){string tmpname = "";int tmpage;cout << "\n请输入老师名字:";cin >> tmpname;cout << "\n请输入老师年龄:";cin >> tmpage;tmp = new Teacher(tmpname, tmpage, id);map1.insert(pair<string, Person*>(id, tmp));}else{tmp = it->second;}return tmp;}
private:map<string, Person*> map1;
};

参考

  1. 黑马程序员C++入门视频教程(完整版)后记提高
  2. 【设计模式】C语言与C++开发基础
  3. 结构型模式
  4. 23种经典设计模式(附c++实现代码) | 王竹兴 |

http://www.ppmy.cn/news/409210.html

相关文章

期末大作业 | ToDoList网页设计 一个晚上一个奇迹 用户登录界面

目录 一、简要说明 二、登录页核心代码 三、CSS样式代码 四、JavaScript脚本代码 五、页面效果截图 六、我的心得 一、简要说明 在当今这样一个快节奏的时代&#xff0c;每个人的时间都很紧迫&#xff0c;就算是刚刚好的时间&#xff0c;也会因为这样或是那样的“意外”情…

思科的云战略:强制与贪婪

周&#xff0c;大量的思科用户反馈E2700、E3500和E4500这三种型号的Linksys路由器出现了问题。当他们尝试登陆他们的路由器&#xff0c;被要求需要输入/注册用户的“思科连接云”账户信息。出现这样出乎意料的“升级”可以很好的诠释思科的决定多么糟糕。 据思科称&#xff0c;…

Git系列文章之第一章 Git

Git系列文章目录 第一章 Git 文章目录 Git系列文章目录前言第一章 Git第一节 Git的基本概念及安装1.基本概念1.1 为什么要学习这个工具&#xff1f;1.2 什么是版本控制&#xff1f;&#xff08;以论文/ppt修改为例&#xff09;1.3 有什么作用和目的&#xff1f; 2.安装2.1 如何…

Qt串口操作遇到的问题

1.QtSerialport 是我自己定义的串口操作的类&#xff0c;里面的成员有QSerialPort *serialport; 在主程序里&#xff0c;我把串口操作又放到了一个线程里 serialPort new QtSerialport(); serialPortThread new QThread(); serialPort->moveToThread(ser…

酷睿e4500、2G内存、250G硬盘、15M服务器租用800元

www.hb666.net 详细进站查看 QQ 617318712销售热线:0710-3851666 3878666 3858555 全国免费热线:4006760688 机房值班&#xff1a;0710-3178666

oracle数据块过热,寒冬中的温暖-SUN E4500温度过高当机

bash-2.03# /usr/platform/sun4u/sbin/prtdiag -v System Configuration: Sun Microsystems sun4u 8-slot Sun Enterprise E4500/E5500 系统时钟频率&#xff1a;100 MHz 内存大小&#xff1a;2048Mb CPUs Run Ecache CPU CPU Brd CPU Module MHz MB Impl. Mask --- --- ----…

95后阿里P7工资单曝光:狠补了两眼泪汪汪,真香...

不久后又是金九银十晒薪资的又多了起来&#xff0c;有服务员、工人、护士、教师还有“程序猿”。互联网成为了21世纪的一个新物种&#xff0c;不仅使工作轻松&#xff0c;收入也相当可观&#xff0c;这就引起了大量的互联网新人加入。程序员这类技术工种在大多数人眼里都是“高…

[Linux] execute golang in linux

1.下载安装包 到官网下载Go语言安装包 go.dev/dl/ 2. 进行解压操作 /opt/go tar -zxvf go1.20.3.linux-amd64.tar.gz 3. 安装完成后,删除安装包 rm -f go1.20.3.linux-amd64.tar.gz 4. 将解压后的Go文件夹移动到 /usr/local/目录下 cp -r /opt/go/go /usr/local -r 5.…