古月不傲 发表于 2020-11-14 15:15

适配器、原型、单例模式

本帖最后由 古月不傲 于 2020-11-14 15:17 编辑

适配器模式
#include <iostream>

using namespace std;

// 适配器模式
namespace adapter_pattern {
enum media_types
{
    MP3,
    MP4,
    WAV
};

// 抽象一个媒体播放器
class abstract_media_player
{
public:
    virtual void play(media_types type, string name) = 0;
    virtual ~abstract_media_player() {}
};

// 抽象一个高级的媒体播放器
class abstract_advanced_media_player
{
public:
    virtual void play_mp4(string name) = 0;
    virtual void play_wav(string name) = 0;
    virtual ~abstract_advanced_media_player() {}
};

// mp4播放器
class mp4_player : public abstract_advanced_media_player
{
public:
    virtual void play_mp4(string name) override {
      printf("播放mp4类型:%s\n", name.c_str());
    }
    // 什么都不做
    virtual void play_wav(string name) override {}
};

// wav播放器
class wav_player : public abstract_advanced_media_player
{
public:
    // 什么都不做
    virtual void play_mp4(string name) override {}
    virtual void play_wav(string name) override {
      printf("播放wav类型:%s\n", name.c_str());
    }
};

// 适配器 桥梁 包含一个高级的媒体播放器 让他拥有播放高级功能
class adapter_media_player : public abstract_media_player
{
public:
    adapter_media_player(media_types type) {
      switch (type)
      {
      case MP4: {
            this->m_ab_adv = new mp4_player;
            break;
      }
      case WAV: {
            this->m_ab_adv = new wav_player;
            break;
      }   
      default: {
            this->m_ab_adv = nullptr;
            break;
      }
      }
    }
    void play(media_types type, string name) {
      switch (type)
      {
      case MP4: {
            this->m_ab_adv->play_mp4(name);
            delete this->m_ab_adv;
            break;
      }
      case WAV: {
            this->m_ab_adv->play_wav(name);
            delete this->m_ab_adv;
            break;
      }   
      default: {
            printf("不支持该种类型!\n");
            break;
      }
      }
    }
private:
    abstract_advanced_media_player *m_ab_adv;
};

// mp3播放器 让mp3包含一个适配器, 强行拥有播放其它格式的功能
class mp3_player : public abstract_media_player
{
public:
    void play(media_types type, string name) override {
      switch (type)
      {
      case MP3: {
            printf("播放MP3类型:%s\n", name.c_str());
            break;
      }
      case MP4: case WAV: {
            this->m_adapter_player = new adapter_media_player(type);
            this->m_adapter_player->play(type, name.c_str());
            delete this->m_adapter_player;
            break;
      }
      default: {
            printf("不支持该种类型!\n");
            break;
      }
      }
    }
    void own_something() {}
private:
    adapter_media_player *m_adapter_player;
};
}

// 可以看出只要new一个播放实例就好 它可以播放多种类型
int main(void)
{
    using namespace adapter_pattern;

    abstract_media_player *mp3 = new mp3_player;
    mp3->play(MP3, "世间美好与你环环相扣");
    mp3->play(MP4, "暗香");
    mp3->play(WAV, "带你去旅行");

    delete mp3;


    return 0;
}

// 总结
// 优点:让一个类拥有多种功能
// 缺点:结构复杂,层层嵌套,破坏了类的单一原则性
原型模式
#include <iostream>

using namespace std;

// 原型模式
namespace prototype_pattern {
// 抽象克隆类
class abstract_clone
{
public:
    virtual abstract_clone *clone() = 0;
    virtual void print() = 0;
    virtual ~abstract_clone() {}
};

// 一个实例对象
class sheep : public abstract_clone
{
public:
    sheep(const string &name, int age) : m_age(age)
    , m_name(name) {}
    sheep(const sheep &obj) : m_age(obj.m_age)
    , m_name(obj.m_name) {}
    abstract_clone *clone() override {
      return new sheep(*this);
    }
    void print() override {
      printf("name = %s age = %d\n", this->m_name.c_str(), this->m_age);
      printf("name = %p age = %p\n", &this->m_name, &this->m_age);
    }
private:
    string m_name;
    int m_age;
};
}

// 可以看出只是通过拷贝构造出另一个对象而已 目的是为了简化构造参数的传递,以及不破坏当前的对象
int main(void)
{
    using namespace prototype_pattern;
   
    abstract_clone *ab_xiyangyang = new sheep("喜羊羊", 5);
    ab_xiyangyang->print();
    abstract_clone *ab_clone = ab_xiyangyang->clone();
    ab_clone->print();

    delete ab_clone;
    delete ab_xiyangyang;
    return 0;
}

// 总结
// 优点:简化构造参数传递,不破坏当前的对象
// 缺点:似乎作用并不是很大
单例模式
#include <iostream>

using namespace std;

// 单例模式
namespace single_pattern {
class skills
{
public:
    // 通过公有接口返回一个实例对象 并且利用static的只初始化一次和局部不被释放的特性保证了安全性和内存的有效利用
    static skills &get_instance() {
      static skills s;
      printf("%p\n", &s);
      return s;
    }
public:
    void cast_q() {
      printf("释放q技能\n");
    }
    void cast_w() {
      printf("释放w技能\n");
    }
    void cast_e() {
      printf("释放e技能\n");
    }
    void cast_r() {
      printf("释放r技能\n");
    }
private:
    skills() = default;
    // 禁止拷贝 赋值
    skills(const skills &obj) = delete;
    skills &operator==(const skills &obj) = delete;
    ~skills() = default;
private:
    static skills m_s;
};
}

// 可以看出实例对象使用的是相同的地址空间
int main(void)
{
    using namespace single_pattern;

    for (int i = 0; i < 1000; i++) {
      skills::get_instance().cast_q();
      skills::get_instance().cast_w();
      skills::get_instance().cast_e();
      skills::get_instance().cast_r();
    }

    return 0;
}

// 总结
// 优点:对于需要频繁调用的类建议使用单例模式
// 缺点:似乎没什么缺点

鸭子咯咯哒~ 发表于 2020-11-14 16:21

wow!对于我这样的新人来说很有帮助{:1_887:}

BaseenHomles 发表于 2020-11-14 16:46

学习了,希望楼主能继续分享{:1_921:}

wlwyzyyq 发表于 2020-11-14 17:11

对于我这样的新人来说很有帮助

304775988 发表于 2020-11-14 19:21

可以,复习复习

大山GZ 发表于 2020-11-14 21:02

嚯,可以,还不赖嘛
页: [1]
查看完整版本: 适配器、原型、单例模式