IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> C++装饰模式 -> 正文阅读

[移动开发]C++装饰模式

参考:设计模式C++实现(11)——装饰模式?

1. 首先如果有一台手机,并且你一直在不停的换手机,那么可以关于手机抽象一个类(person),在用具体的手机(iphone)去继承,并通过多态转换(iphone*转person*),从而可以调用统一的抽象接口(phoneTmp->showLook()),这样无论,你换哪个手机,调用的方法(phoneTmp->showLook())都不会变,只会增加代码,不会修改代码。完美符合开闭原则。


#include <stdlib.h>
#include <iostream>

class person {
public:
    virtual void showLook() = 0;
};

class iphone : public person {
public:
    virtual void showLook() {
        printf("iphone 裸机\r\n");
    }
private:
    person *mPhone;
};

int main() {
    person *phoneTmp = new iphone;
    phoneTmp->showLook();
}

2. 好现在买回来了手机你想给手机贴个膜。于是你的代码可能会变为下面这样。通过继承且在子类添加方法


#include <stdlib.h>
#include <iostream>
#include <string>

class phone {
public:
    virtual void showLook() = 0;
};

class iphone : public phone {
public:
    iphone(std::string nm) {
        name = nm;
    };
    virtual void showLook() {
        printf("%s\r\n", name.c_str());
    }
private:
    phone *mPhone;
    std::string name;
};

class DecorateMo : public phone {
public:
    DecorateMo(phone* mp) {
        mPhone1 = mp;
    };
    virtual void showLook() {
        mPhone1->showLook();
        addMo();
    }

private:
    phone* mPhone1;
    void addMo() {
        printf(" 贴膜\r\n");   
    };
};


int main() {
    phone* tmp = new DecorateMo(new iphone("XXX的iphone"));
    tmp->showLook();
}

3.这么看单独没啥问题,但过了几天你又要装个手机壳,同上,你又要去继承写一个类DecorateKe, 一样的步骤,实现出来大概是这样的。


#include <stdlib.h>
#include <iostream>
#include <string>

class person {
public:
    virtual void showLook() = 0;
};

class iphone : public person {
public:
    iphone(std::string nm) {
        name = nm;
    };
    virtual void showLook() {
        printf("%s ", name.c_str());
    }
private:
    person *mPhone;
    std::string name;
};

class DecorateMo : public person {
public:
    DecorateMo(person* mp) {
        mPhone1 = mp;
    };
    virtual void showLook() {
        mPhone1->showLook();
        addMo();
    }

private:
    person* mPhone1;
    void addMo() {
        printf("贴膜\r\n");   
    };
};

class DecorateKe : public person {
public:
    DecorateKe(person* mp) {
        mPhone1 = mp;
    };
    virtual void showLook() {
        mPhone1->showLook();
        addKe();
    }

private:
    person* mPhone1;
    void addKe() {
        printf("装手机壳\r\n");   
    };
};

int main() {
    person* tmp = new DecorateMo(new iphone("XXX的iphone"));
    // tmp->showLook();
    DecorateKe *tmp1 = new DecorateKe(tmp);
    tmp1->showLook();
}

4. 所以为什么选择装饰模式,不用继承呢?

比如现在需要算配件:手机壳,膜一共需要多少钱?那么如果用现有的结构,就需要在person类加一个cost()方法,在相关类加方法,在加个全局变量,写出来大概是这样的。


#include <stdlib.h>
#include <iostream>
#include <string>
    int total;

class person {
   public:
    virtual void showLook() = 0;
    virtual void cost() {
        printf("一共用了%d元\r\n", total);
    };

};

class iphone : public person {
public:
    iphone(std::string nm) {
        name = nm;
    };
    virtual void showLook() {
        printf("%s ", name.c_str());
    }
private:
    person *mPhone;
    std::string name;
};


class DecorateMo : public person {
public:
    DecorateMo(person* mp) {
        mPhone1 = mp;
    };
    virtual void showLook() {
        mPhone1->showLook();
        addMo();
    }

private:
    person* mPhone1;
    void addMo() {
        printf("贴膜\r\n");
        cost();
    };
    virtual void cost() {
        total += 20;
        printf("20\r\n");
    }
};

class DecorateKe : public person {
public:
    DecorateKe(person* mp) {
        mPhone1 = mp;
    };
    virtual void showLook() {
        mPhone1->showLook();
        addKe();
    }

private:
    person* mPhone1;
    void addKe() {
        printf("装手机壳\r\n");
        cost();
    };
    virtual void cost() {
        total += 30;
        printf("30\r\n");
    }
};

int main() {
    person *tmpPhone = new iphone("XXX的iphone");
    person *tmp = new DecorateMo(tmpPhone);
    // tmp->showLook();
    person *tmp1 = new DecorateKe(tmp);
    tmp1->showLook();
    tmpPhone->cost();
}

5.?或许有其他办法,但没有可以不修改person类的办法实现这个功能。。因为很多东西继承peson,改动person如果逻辑复杂了,会带来新风险,这样很不好,我们希望哪个person类不要被修改,所以装饰模式的作用就体现出来了。

装饰模式的优点:就是便于扩展,并且不修改基类。且扩展性非常好,不用修改任何原有代码。

那么用装饰模式怎么增加cost功能呢?首先加个抽象的Decorate类,但为了保持之前的showLook()方法,我们需要用Decorate类继承person类。

  • 感觉区别不是很大,但不修改person类会直接做到对person类和他的子类的BUG的0输入。。
  • 并且这种模式可以增加任意的新功能,且可以保持不修改之前的person类相关代码,这个特性完全符合了开闭思想,降低风险的引入。

#include <stdlib.h>
#include <iostream>
#include <string>
    int total;

class person {
   public:
    virtual void showLook() = 0;
};

class iphone : public person {
public:
    iphone(std::string nm) {
        name = nm;
    };
    virtual void showLook() {
        printf("%s\r\n", name.c_str());
    }
private:
    person *mPhone;
    std::string name;
};
class Decorate : public person{
public:
    virtual void cost() {
        printf("total = %d\r\n", total);
    };
    virtual void showLook() = 0;
};


class DecorateMo : public Decorate {
   public:
    DecorateMo(person* mp) {
        mPhone1 = mp;
    };
    virtual void showLook() {
        addMo();
    }
    void costTotal() { Decorate::cost(); }

   private:
    person* mPhone1;
    void addMo() {
        printf("贴膜\r\n");
        cost();
    };
    virtual void cost() {
        total += 20;
        printf("20\r\n");
    }
};

class DecorateKe : public Decorate {
public:
    DecorateKe(person* mp) {
        mPhone1 = mp;
    };
    virtual void showLook() {
        addKe();
    }
    void costTotal() {Decorate::cost(); }

private:
    person* mPhone1;
    void addKe() {
        printf("装手机壳\r\n");
        cost();
    };
    virtual void cost() {
        total += 30;
        printf("30\r\n");
    }
};
int main() {
    person *tmpPhone = new iphone("XXX的iphone");
    tmpPhone->showLook();

    DecorateMo *tmp = new DecorateMo(tmpPhone);
    tmp->showLook();
    tmp->costTotal();
    person *tmp1 = dynamic_cast<person *>(tmp);

    DecorateKe *tmp2 = new DecorateKe(tmp1);
    tmp2->showLook();
    tmp2->costTotal();

}

总结: 装饰者模式适用于:新增加的功能点,在不改变现有的子类,父类的前提下,抽象一个接口类(Decarate),说白了,为了不改变原有的基类,加了一个中间人Decarate去继承Person,这样新加的功能,与之前的代码完全解耦。所以当需要新加一个功能点的时候,考虑用装饰者模式吧。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-10-03 17:12:26  更:2021-10-03 17:12:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:10:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码