• 【19】c++设计模式——>桥接模式


    桥接模式的定义

    C++的桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与实现部分分离,使得它们可以独立地变化。桥接模式的核心思想是利用组合关系代替继承关系,将系统划分成多个独立的、功能不同的类层次结构,并通过桥接类将它们连接起来。
    在桥接模式中,有两个重要的概念:抽象化(Abstraction)和实现化(Implementation),它们分别对应了系统的抽象部分和实现部分。抽象化负责定义接口,并维护一个指向实现化对象的指针;实现化则负责定义具体的实现方法。

    使用场景

    关于桥接模式的使用对应的场景有很多,比如:
    1.空调、电视等和他们对应的遥控器:空调、电视机是抽象,遥控器是实现;
    2.手机品牌和手机软件:手机品牌是抽象,手机软件是实现;
    3.跨品台的GUI在不同平台上运行:程序的GUI层是抽象,操作系统API是实现。
    4.假设我们正在开发一个图形绘制应用程序,支持多种图形和不同的绘制渲染方式。其中,图形包括圆形、矩形等,渲染方式包括使用直线绘制、使用虚线绘制等。这两个维度的变化都可能会在未来进行扩展和修改。
    就是说将具体的图形和具体的渲染桥接在一起,实现图形和渲染方式之间的解耦,我们可以在客户端代码中使用桥接模式,通过实例化具体的图形对象和具体的渲染实现对象,将它们桥接在一起,并进行绘制:

    #include 
    
    // Abstract Render API
    class RenderAPI {
    public:
        virtual void renderCircle() = 0;         // 抽象的渲染圆形方法
        virtual void renderRectangle() = 0;      // 抽象的渲染矩形方法
    };
    
    // Concrete Line Renderer
    class LineRenderer : public RenderAPI {
    public:
        void renderCircle() override {
            std::cout << "Render Circle with lines." << std::endl;     // 使用线条渲染圆形
        }
    
        void renderRectangle() override {
            std::cout << "Render Rectangle with lines." << std::endl;  // 使用线条渲染矩形
        }
    };
    
    // Concrete Dashed Line Renderer
    class DashedLineRenderer : public RenderAPI {
    public:
        void renderCircle() override {
            std::cout << "Render Circle with dashed lines." << std::endl;    // 使用虚线渲染圆形
        }
    
        void renderRectangle() override {
            std::cout << "Render Rectangle with dashed lines." << std::endl; // 使用虚线渲染矩形
        }
    };
    
    // Abstract Shape
    class Shape {
    protected:
        RenderAPI* renderAPI;
    
    public:
        Shape(RenderAPI* api) : renderAPI(api) {}
    
        virtual void draw() = 0;   // 抽象的绘制方法,具体的形状类将实现这个方法
    };
    
    // Concrete Circle
    class Circle : public Shape {
    public:
        Circle(RenderAPI* api) : Shape(api) {}
    
        void draw() override {
            renderAPI->renderCircle();   // 调用渲染API的渲染圆形方法来绘制圆形
        }
    };
    
    // Concrete Rectangle
    class Rectangle : public Shape {
    public:
        Rectangle(RenderAPI* api) : Shape(api) {}
    
        void draw() override {
            renderAPI->renderRectangle();   // 调用渲染API的渲染矩形方法来绘制矩形
        }
    };
    
    int main() {
        // 创建一个圆形对象,并设置使用线条渲染的渲染API
        Shape* circleShape = new Circle(new LineRenderer());
        // 创建一个矩形对象,并设置使用虚线渲染的渲染API
        Shape* rectangleShape = new Rectangle(new DashedLineRenderer());
    
        // 绘制圆形
        circleShape->draw();
        // 绘制矩形
        rectangleShape->draw();
    
        delete circleShape;
        delete rectangleShape;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    海贼王实例

    对于海贼王中来说,有海军,有海贼团,不论是海军还是海贼团,他们都有自己的船,海军的船叫军舰,海贼团的船叫海贼船,因此,我们需要将船和团队分开;
    船+海贼团 -->海贼船
    船+海军—>军舰
    对于一个海贼团或者一支海军部队来说,光有船是不完整的,船只是这个团队的抽象,如果想要让它鲜活起来就必要要有由人组成的团队,也就是抽象的具体实现。所以,在这个抽象类中包含了一个团队对象,船和团队二者之间的关系可以看做是聚合关系。
    我们以草帽海贼团和斯摩格海贼团为例:

    #include 
    #include
    #include
    using namespace std;
    
    //不论是哪艘船上的船员肯定都是由一些个人的身份信息,为了将这些信息记录下来,先定一个存储数据的类:
    //人员信息
    struct Person
    {
    	Person(string name, string job, string ability, string reward, string beizhu=string())
    	{
    		this->name = name;
    		this->job = job;
    		this->ability = ability;
    		this->reward = reward;
    		this->beizhu = beizhu;
    	}
    	~Person()
    	{
    		cout << name << "被析构了..." << endl;
    	}
    	string name;     //姓名
    	string job;      //工作
    	string ability;  //能力
    	string reward;   //赏金
    	string beizhu;   //备注
    };
    //关于团队的成员组成可以是海贼,也可以是海军,所以先定义一个团队的抽象类
    class AbstractTeam
    {
    public:
    	AbstractTeam(string name):m_teamName(name) {}
    	//获取团队姓名
    	string getTeamName()
    	{
    		return m_teamName;
    	}
    	//给团队添加成员,用map保存,键是姓名,值是Person类
    	void addMember(Person* p)
    	{
    		m_infoMap.insert(make_pair(p->name,p));
    	}
    	//打印成员信息
    	void show()
    	{
    		cout << m_teamName << ":" << endl;
    		//遍历map
    		for(const auto & item:m_infoMap)
    		{
    			cout << "【Name: " << item.second->name
    				<< ", Job: " << item.second->job
    				<< ", Ability: " << item.second->ability
    				<< ", MoneyReward: " << item.second->reward
    				<< ", BeiZhu: " << item.second->beizhu
    				<< "】" << endl;
    		}
    	}
    	//执行任务函数,海军和海贼的任务不同,因此是纯虚函数,子类中重写
    	virtual void executeTask() = 0;
    	//虚析构函数,释放类时,将m_infoMap保存的团队所有成员都析构掉
    	virtual ~AbstractTeam()
    	{
    		for (const auto& item : m_infoMap)
    		{
    			delete item.second;
    		}
    	}
    protected:
    	string m_teamName = string();
    	//该团队的所有成员
    	map m_infoMap;
    };
    //具体的团队类,路飞的草帽海贼团和斯摩格的海军团
    //草帽海贼团
    class CaoMaoTeam :public AbstractTeam
    {
    public:
    	using AbstractTeam::AbstractTeam;//继承基类的构造函数,而不用子类重新实现相同的构造函数
    	void executeTask() override
    	{
    		cout << "在海上冒险,找到 ONE PIECE 成为海贼王!" << endl;
    	}
    };
    //斯摩格海军团队
    class SmokeTeam :public AbstractTeam
    {
    public:
    	using AbstractTeam::AbstractTeam;
    	void executeTask()override
    	{
    		cout << "为了正义,先将草帽一伙一网打尽!!!" << endl;
    	}
    };
    //船类
    /*不论是海军还是海贼在大海上航行都需要船,虽然他们驾驶的船只不同,
    但是有很多属性还是一致的,所以我们可以先定义一个船的抽象类*/
    class AbstructShip
    {
    public:
    	AbstructShip(AbstractTeam* team) :m_team(team) {} //团队+船
    	void showTeam()
    	{
    		m_team->show();
    		m_team->executeTask();
    	}
    	virtual string getName() = 0;
    	virtual void feature() = 0; //纯虚函数描述船的特点,在不同的子类中都需要重写
    	virtual~AbstructShip() {}
    protected:
    	AbstractTeam* m_team = nullptr; //这里将团队和船绑定在一起了
    };
    //梅丽号
    class Merry :public AbstructShip
    {
    public:
    	using AbstructShip::AbstructShip;
    	string getName() override
    	{
    		return string("前进梅丽号");
    	}
    	void feature()override
    	{
    		cout << getName() << "--船首为羊头,在司法岛化身船精灵舍己救下草帽一伙" << endl;
    	}
    };
    //海军无敌战舰
    class HaiJunJian :public AbstructShip
    {
    public:
    	using AbstructShip::AbstructShip;
    	string getName()override
    	{
    		return string("无敌海军号");
    	}
    	void feature() override
    	{
    		cout << getName() << " -- 船底由海楼石建造, 可以穿过无风带的巨大炮舰!" << endl;
    	}
    };
    int main()
    {
    	//草帽海贼团
    	CaoMaoTeam* caomao = new CaoMaoTeam("草帽海贼团");
    	Person* luffy = new Person("路飞", "船长", "橡胶果实能力者", "30亿贝里", "爱吃肉");
    	Person* zoro = new Person("索隆", "剑士", "三刀流", "11亿1100万贝里", "路痴");
    	Person* sanji = new Person("山治", "厨师", "隐形黑", "10亿3200万贝里", "好色");
    	Person* nami = new Person("娜美", "航海士", "天候棒+宙斯", "3亿6600万贝里", "喜欢钱");
    	caomao->addMember(luffy);
    	caomao->addMember(zoro);
    	caomao->addMember(sanji);
    	caomao->addMember(nami);
    	Merry* sunny = new Merry(caomao);
    	sunny->feature();
    	sunny->showTeam();
    	//斯摩格
    	SmokeTeam* smoke =  new SmokeTeam("斯摩格海军团");
    	Person* smoker = new Person("斯摩格", "中将", "冒烟果实能力者", "", "爱吃烟熏鸡肉");
    	Person* dasiqi = new Person("达斯琪", "大佐", "一刀流", "", "近视");
    	smoke->addMember(smoker);
    	smoke->addMember(dasiqi);
    	HaiJunJian* ship = new HaiJunJian(smoke);
    	ship->feature();
    	ship->showTeam();
    
    	delete caomao;
    	delete sunny;
    	delete smoke;
    	delete ship;
    	return 0;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171

    在这里插入图片描述

  • 相关阅读:
    人工智能第2版学习——人工智能中的逻辑2
    【场景化解决方案】瓴羊“呼叫中心”,提升企业CRM管理效率
    Android中使用kotlin进行xutils数据库版本升级
    设计模式总结(三)
    网络技术五:IP基本原理
    什么是Wi-Fi保护设置(WPS),以及如何使用它?这里有详细解释
    【软考架构】2022年架构案例问题总结
    UE5场景逐渐变亮问题
    学习paddle-detection(paddlex的使用)
    SpringBoot+Vue+Element-UI实现家具商城系统
  • 原文地址:https://blog.csdn.net/weixin_42097108/article/details/133625901