设计模式——结构型模式

前言

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

结构型模式

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

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++实现代码) | 王竹兴 |
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
针对23种设计模式,分别写了demo并画了类图帮助理解。 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式代理模式、外观模式、桥接模式、组合模式、享元模式。 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。 其实还有两类:并发型模式和线程池模式。 二、设计模式的六大原则 1、开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。 2、里氏代换原则(Liskov Substitution Principle) 里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。—— From Baidu 百科 3、依赖倒转原则(Dependence Inversion Principle) 这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。 4、接口隔离原则(Interface Segregation Principle) 这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。 5、迪米特法则(最少知道原则)(Demeter Principle) 为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。 6、合成复用原则(Composite Reuse Principle) 原则是尽量使用合成/聚合的方式,而不是使用继承。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值