针对类与对象的组织结构
类适配器模式
适配器,在生活中又称转换器。现在的手机基本都割去了3.5mm的耳机接口,此时只有有线耳机,要听歌就需要一个转换器将3.5mm接口转成手机有的type-c的接口
适配器模式(Adapter Pattern)充当两个不兼容接口之间的桥梁,属于结构型设计模式。它通过一个中间件(适配器)将一个类的接口转换成客户期望的另一个接口,使原本不能一起工作的类能够协同工作。
cpp
#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不是接口而是抽象类的话就用不了了。所以提出对象适配器:
cpp
#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系列 麒麟 联发科 猎户座。不能每一种配置都写一个类就太麻烦了,所以有了桥接模式,可以通过多个类桥接成一个产品类。
优势:可以通过多个维度来自由设定配置
cpp
#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;
}
组合模式
对多个组件进行统一一样的操作
组合模式实际上就是将多个组件进行组合,让用户可以对它们进行一致性处理。比如我们的文件夹,一个文件夹中可以有很多个子文件夹或是文件。
意图:通过树形结构表示对象的层次关系,使得客户端可以一致地对待单个对象和组合对象,而无需关心它们的具体类型。
cpp
#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元。
cpp
#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;
}
bash
装饰方法:我是操作前逻辑
我是业务方法
装饰方法:我是操作后逻辑
装饰方法:我是操作前逻辑
装饰方法:我是操作前逻辑
我是业务方法
装饰方法:我是操作后逻辑
装饰方法:我是操作后逻辑
代理模式
和装饰模式代码一模一样,但核心是思想不同
代理模式是讲DecoratorImpl给别人代理了,装饰模式是DecoratorImpl自己增强。
装饰模式和代理模式:
结构相同:都实现同一个接口/抽象类
作用不同:
装饰器模式强调的是增强自身,在被装饰之后你能够在被增强的类上使用增强后的功能,增强后你还是你,只不过被强化了而已;
代理模式强调要让别人帮你去做事情,以及添加一些本身与你业务没有太多关系的事情(记录日志、设置缓存等)重点在于让别人帮你做。
cpp
//代理者需要将代理目标组合到类中
class Decorator : public Base {
protected:
std::shared_ptr<Base> base; // 组合方式持有被装饰对象
public:
Decorator(std::shared_ptr<Base> base) : base(base) {}
void test() override {
base->test(); // 调用被装饰对象的业务方法
}
};
外观模式
可以理解为门面模式,将需要通过操作多个类实现的一个功能封装到一个类中,便于使用
当每个功能是一个系统,完成一个业务需要多个功能时就需要分别调用多个系统,此时就可以将一个业务需要使用的多个系统封装成一个门面系统,只要调用该门面系统即可完成该业务。
举例:比如现在我们设计了三个子系统,分别是排队、结婚、领证,正常情况下我们是需要分别去找这三个部门去完成的,但是现在我们通过门面统一来完成
意图:隐藏子系统的复杂性,提供一个统一的高层接口,使客户端可以更简单地使用子系统。
cpp
#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类方法
享元模式的核心在于共享对象,以减少对象的创建次数,节省内存。
意图:通过共享对象来减少内存占用,提高系统的性能,特别是在需要频繁创建大量相似对象的场景中。
cpp
#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;
}