首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >结构型之装饰模式C++实现

结构型之装饰模式C++实现

作者头像
用户9831583
发布2022-06-16 15:13:03
发布2022-06-16 15:13:03
2520
举报
文章被收录于专栏:码出名企路码出名企路

需求分析:需要对现有产品增加新的功能或美化其外观,房子装修、相片加相框。在软件开发过程中,有时想用一些现存的组件。这些组件可能只是完成了一些核心功能。但在不改变其结构的情况下,可以动态地扩展其功能

装饰模式:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)。

优点:

  • 扩展对象的功能比采用继承方式更加灵活。
  • 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合。

缺点:装增加了许多子类,如果过度使用会使程序变得很复杂。

核心思想:通常情况下,扩展一个类的功能会使用继承方式来实现。但继承具有静态特征,耦合度高,并且随着扩展功能的增多,子类会很膨胀。如果使用组合关系来创建一个包装对象(即装饰对象)来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能。

主要角色:

  1. 抽象构件角色:定义一个抽象接口以规范准备接收附加责任的对象。
  2. 具体构件角色:实现抽象构件,通过装饰角色为其添加一些职责。
  3. 抽象装饰角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
  4. 具体装饰角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

具体案例:

小码路下班后与朋友一起去吃火锅,火锅基本套餐是200元,如果需要加配菜,另外收费。小码路喜欢吃海带,大虾。问最后总共花费类多少钱?

第一步:抽象构件角色

代码语言:javascript
复制
#pragma once
#include <iostream>
using namespace std;

//定义一个顶层接口
//定义总共花费钱和总共的菜品
class HuoGuo
{
    public:
        virtual float totalPrice()=0;
        virtual string totalCai()=0;
};

第二步:具体构件角色

代码语言:javascript
复制
//定义基类实现顶层接口
//将顶层接口进行赋值操作后,再次调用顶层接口里的方法
class HuoGuoCaiLei:public HuoGuo
{
    public:
        HuoGuo *huoguo;
    public:
        //将顶层接口以构造参数的方式传递进来
        HuoGuoCaiLei(HuoGuo *hg)
        {
            this->huoguo=hg;
        }
        //重写顶层接口的方法,这里调用里面的方法
        float totalPrice()
        {
            return huoguo->totalPrice();
        }
        string totalCai()
        {
            return huoguo->totalCai();
        }
};

第三步:抽象装饰角色

代码语言:javascript
复制
//接口和基类已封装完成,接下来定义上面提到的角色
//套餐价格200,是必点的,只需要实现顶层接口,复制操作就好
//添加的配菜必须依附这个
class TaoCanHuoGuo:public HuoGuo
{
    public:
        //套餐 200
        float totalPrice()
        {
            return 200;
        }
        //核心配菜,简写套餐菜
        string totalCai()
        {
            return "套餐菜";
        }
};

第四步:具体装饰角色

代码语言:javascript
复制
//此时可以添加额外的配菜了
//上面已经定义了添加配菜的基类,只要继承然后在子类设置附加菜品的价格就好
//添加海带
class HaiDai:public HuoGuoCaiLei
{
     public:
           HuoGuo *hg;
    public:
        HaiDai(HuoGuo *hg):HuoGuoCaiLei(hg)
        {

        }
        
        //在父类的基础上增加海带的价格 30
        float totalPrice()
        {
            return HuoGuoCaiLei::totalPrice()+30;
        }
        string totalCai()
        {
            return HuoGuoCaiLei::totalCai()+"添加了火锅配菜,";
        }
};

//添加大虾
class DaXia:public HuoGuoCaiLei
{
    public:
       HuoGuo *hg;
    public:
        DaXia(HuoGuo *hg):HuoGuoCaiLei(hg)
        {
            
        }
        //在父类的基础上增加海带的价格 60
        float totalPrice()
        {
            return HuoGuoCaiLei::totalPrice()+60;
        }
        string totalCai()
        {
            return HuoGuoCaiLei::totalCai()+"添加了大虾配菜,";
        }
};

第五步:主函数

代码语言:javascript
复制
#include "m.h"

int main()
{
    //实例化一个套餐火锅
    HuoGuo *tchg=new TaoCanHuoGuo();
    cout<<tchg->totalCai()<<" 总消费: "<<tchg->totalPrice()<<endl;
    
    //添加海带
    tchg=new HaiDai(tchg);
    cout<<tchg->totalCai()<<" 总消费: "<<tchg->totalPrice()<<endl;

    //添加大虾
     tchg=new DaXia(tchg);
    cout<<tchg->totalCai()<<" 总消费: "<<tchg->totalPrice()<<endl;

    //再添加一份大虾
    tchg=new DaXia(tchg);
    cout<<tchg->totalCai()<<" 总消费: "<<tchg->totalPrice()<<endl;

    return 0;
}

结果显示:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码出名企路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档