设计模式-结构性设计模式(针对类与对象的组织结构) - 指南

针对类与对象的组织结构

类适配器模式

适配器,在生活中又称转换器。现在的手机基本都割去了3.5mm的耳机接口,此时只有有线耳机,要听歌就需要一个转换器将3.5mm接口转成手机有的type-c的接口
适配器模式(Adapter Pattern)充当两个不兼容接口之间的桥梁,属于结构型设计模式。它通过一个中间件(适配器)将一个类的接口转换成客户期望的另一个接口,使原本不能一起工作的类能够协同工作。

#include <iostream>
  #include <string>
    // 父类
    class ThirtyFiveMM {
    public:
    std::string listenMusic() {
    return "有线耳机听歌!";
    }
    };
    // typeC接口
    class TypeC {
    public:
    virtual std::string listen() = 0; // 纯虚函数,定义接口
    virtual ~TypeC() {} // 虚析构函数
    };
    // 子类作适配器,继承ThirtyFiveMM,实现TypeC接口
    class Adapter : public ThirtyFiveMM, public TypeC {
    public:
    std::string listen() override {
    return ThirtyFiveMM::listenMusic();
    }
    };
    // 主方法
    void main() {
    // TestSupplier supplier; // 假设TestSupplier是一个类,这里只是示例
    Adapter adapter;
    test(&adapter); // 使用适配器将35MM转换为TypeC接口
    }
    void test(TypeC* typec) {
    std::cout << "成功得到:" << typec->listen() << std::endl;
      }
      // 假设的TestSupplier类
      class TestSupplier {
      // 空类,仅作为示例
      };

对象适配器

因为类适配器会占用一个继承位,而java又是单继承的。如果typeC不是接口而是抽象类的话就用不了了。所以提出对象适配器:

#include <iostream>
  #include <string>
    // 父类
    class ThirtyFiveMM {
    public:
    std::string listenMusic() {
    return "有线耳机听歌!";
    }
    };
    // typeC接口
    class TypeC {
    public:
    virtual std::string listen() = 0; // 纯虚函数,定义接口
    virtual ~TypeC() {} // 虚析构函数
    };
    // 适配器类,实现TypeC接口
    class Adapter : public TypeC {
    private:
    ThirtyFiveMM* thirtyFiveMM; // 持有35MM类型的对象
    public:
    Adapter(ThirtyFiveMM* thirtyFiveMM) : thirtyFiveMM(thirtyFiveMM) {}
    std::string listen() override {
    return thirtyFiveMM->listenMusic();
    }
    };
    // 主方法
    int main() {
    ThirtyFiveMM thirtyFiveMM; // 创建35MM类型的对象
    Adapter adapter(&thirtyFiveMM); // 创建适配器对象,传入35MM对象
    test(&adapter); // 调用test方法,传入适配器对象
    return 0;
    }
    void test(TypeC* typec) {
    std::cout << "成功得到:" << typec->listen() << std::endl;
      }

桥接模式

选择不同的配置(零件)组成一个东西(先组一个再组一个,一层一层的基础来达到组零件的目的)
同一种产品有着不同的配置,就像手机有:运行内存 4 6 8g,存储内存:64 128 256g,芯片:骁龙 A系列 麒麟 联发科 猎户座。不能每一种配置都写一个类就太麻烦了,所以有了桥接模式,可以通过多个类桥接成一个产品类。

优势:可以通过多个维度来自由设定配置

#include <iostream>
  #include <string>
    // 第一层类:继承该类可以自定义芯片类型
    class AbstractPhone {
    protected:
    class Size* size; // 这里是描述存储内存
    public:
    AbstractPhone(class Size* size) : size(size) {}
    virtual std::string getType() = 0; // 纯虚函数,定义芯片类型
    virtual ~AbstractPhone() {
    delete size; // 释放Size对象
    }
    };
    // 接口及实现类
    class Size {
    public:
    virtual std::string getSize() = 0; // 纯虚函数,定义接口
    virtual ~Size() {} // 虚析构函数
    };
    class Size256G : public Size {
    public:
    std::string getSize() override {
    return "256g内存";
    }
    };
    // 第二层类:继承该类可以自定义芯片类型和存储内存的尺度大小
    class RefinedAbstractPhone : public AbstractPhone {
    public:
    RefinedAbstractPhone(Size* size) : AbstractPhone(size) {}
    std::string getSize() { // 添加尺寸维度获取方式
    return size->getSize();
    }
    };
    // 产品类:继承第二层类,然后自定义存储内存大小和芯片种类
    class HUAWEI : public RefinedAbstractPhone {
    public:
    HUAWEI(Size* size) : RefinedAbstractPhone(size) {}
    std::string getType() override {
    return "华为手机"; // 返回手机品牌类型
    }
    };
    // 主方法
    int main() {
    Size256G* size = new Size256G();
    HUAWEI huawei(size);
    std::cout << huawei.getType() << std::endl;
    std::cout << huawei.getSize() << std::endl;
    return 0;
    }

组合模式

对多个组件进行统一一样的操作
组合模式实际上就是将多个组件进行组合,让用户可以对它们进行一致性处理。比如我们的文件夹,一个文件夹中可以有很多个子文件夹或是文件。
意图:通过树形结构表示对象的层次关系,使得客户端可以一致地对待单个对象和组合对象,而无需关心它们的具体类型。

#include <iostream>
  #include <vector>
    #include <string>
      #include <memory>
        // 组件接口
        class Component {
        public:
        virtual ~Component() = default;
        virtual void add(std::shared_ptr<Component> component) = 0;
          virtual void remove(std::shared_ptr<Component> component) = 0;
            virtual void display(int depth) const = 0;
            };
            // 叶子类:文件
            class File : public Component {
            private:
            std::string name;
            public:
            File(const std::string& name) : name(name) {}
            void add(std::shared_ptr<Component> component) override {
              throw std::logic_error("File cannot add components");
              }
              void remove(std::shared_ptr<Component> component) override {
                throw std::logic_error("File cannot remove components");
                }
                void display(int depth) const override {
                std::cout << std::string(depth, '-') << name << std::endl;
                }
                };
                // 组合类:目录
                class Directory : public Component {
                private:
                std::string name;
                std::vector<std::shared_ptr<Component>> children;
                  public:
                  Directory(const std::string& name) : name(name) {}
                  void add(std::shared_ptr<Component> component) override {
                    children.push_back(component);
                    }
                    void remove(std::shared_ptr<Component> component) override {
                      children.erase(std::remove(children.begin(), children.end(), component), children.end());
                      }
                      void display(int depth) const override {
                      std::cout << std::string(depth, '-') << name << std::endl;
                      for (const auto& child : children) {
                      child->display(depth + 1);
                      }
                      }
                      };
                      // 主方法
                      int main() {
                      // 创建文件和目录
                      std::shared_ptr<File> file1 = std::make_shared<File>("file1.txt");
                        std::shared_ptr<File> file2 = std::make_shared<File>("file2.txt");
                          std::shared_ptr<Directory> dir1 = std::make_shared<Directory>("dir1");
                            std::shared_ptr<Directory> dir2 = std::make_shared<Directory>("dir2");
                              // 构建树形结构
                              dir1->add(file1);
                              dir1->add(file2);
                              dir2->add(dir1);
                              // 显示树形结构
                              dir2->display(0);
                              return 0;
                              }

装饰模式

通过B类 实现对A类方法执行前后,分别多执行一些操作。类似于AOP
Base是抽象类/接口,有一个实现类实现其里面具体的业务方法。Decorator可以理解为是一个给装饰者们的一个抽象类,然后不同的装饰者再去具体继承Decorator并在业务方法前后进行修饰。

适用:业务功能前后实现一些操作。如:在支付前提醒是否需要支付xxx元。

#include <iostream>
  #include <memory>
    // 顶层抽象类
    class Base {
    public:
    virtual void test() = 0; // 纯虚函数,定义业务方法
    virtual ~Base() = default; // 虚析构函数
    };
    // 业务实现类
    class BaseImpl : public Base {
    public:
    void test() override {
    std::cout << "我是业务方法" << std::endl; // 具体的业务方法
    }
    };
    // 装饰业务类
    class Decorator : public Base {
    protected:
    std::shared_ptr<Base> base; // 组合方式持有被装饰对象
      public:
      Decorator(std::shared_ptr<Base> base) : base(base) {}
        void test() override {
        base->test(); // 调用被装饰对象的业务方法
        }
        };
        // 具体实现装饰业务类
        class DecoratorImpl : public Decorator {
        public:
        DecoratorImpl(std::shared_ptr<Base> base) : Decorator(base) {}
          void test() override {
          std::cout << "装饰方法:我是操作前逻辑" << std::endl;
          Decorator::test(); // 调用基类的test方法,即被装饰对象的业务方法
          std::cout << "装饰方法:我是操作后逻辑" << std::endl;
          }
          };
          // 主方法
          int main() {
          std::shared_ptr<Base> base = std::make_shared<BaseImpl>();
            std::shared_ptr<DecoratorImpl> decorator = std::make_shared<DecoratorImpl>(base); // 将Base实现装饰一下
              std::shared_ptr<DecoratorImpl> outer = std::make_shared<DecoratorImpl>(decorator); // 装饰者还可以嵌套,此时是装饰两次
                decorator->test(); // 装饰一次:装饰前——业务方法——装饰后
                outer->test(); // 装饰两次:装饰前——装饰前——业务方法——装饰后——装饰后
                return 0;
                }
装饰方法:我是操作前逻辑
我是业务方法
装饰方法:我是操作后逻辑
装饰方法:我是操作前逻辑
装饰方法:我是操作前逻辑
我是业务方法
装饰方法:我是操作后逻辑
装饰方法:我是操作后逻辑

代理模式

和装饰模式代码一模一样,但核心是思想不同
代理模式是讲DecoratorImpl给别人代理了,装饰模式是DecoratorImpl自己增强。
装饰模式和代理模式:
结构相同:都实现同一个接口/抽象类
作用不同:
装饰器模式强调的是增强自身,在被装饰之后你能够在被增强的类上使用增强后的功能,增强后你还是你,只不过被强化了而已;
代理模式强调要让别人帮你去做事情,以及添加一些本身与你业务没有太多关系的事情(记录日志、设置缓存等)重点在于让别人帮你做。

//代理者需要将代理目标组合到类中
class Decorator : public Base {
protected:
std::shared_ptr<Base> base; // 组合方式持有被装饰对象
  public:
  Decorator(std::shared_ptr<Base> base) : base(base) {}
    void test() override {
    base->test(); // 调用被装饰对象的业务方法
    }
    };

外观模式

可以理解为门面模式,将需要通过操作多个类实现的一个功能封装到一个类中,便于使用
当每个功能是一个系统,完成一个业务需要多个功能时就需要分别调用多个系统,此时就可以将一个业务需要使用的多个系统封装成一个门面系统,只要调用该门面系统即可完成该业务。
举例:比如现在我们设计了三个子系统,分别是排队、结婚、领证,正常情况下我们是需要分别去找这三个部门去完成的,但是现在我们通过门面统一来完成
意图:隐藏子系统的复杂性,提供一个统一的高层接口,使客户端可以更简单地使用子系统。

#include <iostream>
  // 系统一
  class SubSystemA {
  public:
  void test1() {
  std::cout << "排队" << std::endl;
  }
  };
  // 系统二
  class SubSystemB {
  public:
  void test2() {
  std::cout << "结婚" << std::endl;
  }
  };
  // 系统三
  class SubSystemC {
  public:
  void test3() {
  std::cout << "领证" << std::endl;
  }
  };
  // 门面
  class Facade {
  private:
  SubSystemA a;
  SubSystemB b;
  SubSystemC c;
  public:
  void marry() { // 红白喜事一条龙服务
  a.test1();
  b.test2();
  c.test3();
  }
  };
  // 主方法
  int main() {
  Facade facade;
  facade.marry();
  return 0;
  }

享元模式

核心是共享。当A类方法里写了一个方法,B类中需要同样的方法就可以直接创建A类对象来调用方法或者通过一个方法工厂类收集各个方法,然后B类通过工厂类调用A类方法
享元模式的核心在于共享对象,以减少对象的创建次数,节省内存。
意图:通过共享对象来减少内存占用,提高系统的性能,特别是在需要频繁创建大量相似对象的场景中。

#include <iostream>
  // A类
  class DBUtil {
  public:
  void selectDB() {
  std::cout << "我是数据库操作..." << std::endl;
  }
  };
  // 享元工厂
  class DBUtilFactory {
  private:
  static DBUtil* UTIL; // 享元对象被存放在工厂中
  public:
  static DBUtil* getFlyweight() { // 获取享元对象
  if (UTIL == nullptr) {
  UTIL = new DBUtil();
  }
  return UTIL;
  }
  // 防止拷贝和赋值
  DBUtilFactory(const DBUtilFactory&) = delete;
  DBUtilFactory& operator=(const DBUtilFactory&) = delete;
  // 析构函数,释放资源
  ~DBUtilFactory() {
  delete UTIL;
  }
  };
  // 初始化静态成员变量
  DBUtil* DBUtilFactory::UTIL = nullptr;
  // B类
  class UserService { // 用户服务
  public:
  void service() {
  DBUtil* util = DBUtilFactory::getFlyweight(); // 通过享元工厂拿到DBUtil对象
  util->selectDB(); // 该干嘛干嘛
  }
  };
  // 主方法
  int main() {
  UserService userService;
  userService.service(); // 调用用户服务
  return 0;
  }
posted @ 2025-09-30 08:21  wzzkaifa  阅读(10)  评论(0)    收藏  举报