C++设计模式(桥接、享元、外观、状态)

一、桥接模式

1.定义

将抽象部分与它的实现部分分离,使它们可以独立地变化。

桥接模式通过使用组合关系而不是继承关系来实现解耦,从而提高系统的灵活性和可扩展性。

2.组成

  • 抽象:定义抽象部分的接口,包含一个指向实现类的对象的指针。
  • 扩展抽象:扩展了抽象类,实现抽象部分的接口并添加额外的行为。
  • 实现:定义实现类的接口。
  • 具体实现:实现了实现类的接口。

3.示例

cpp 复制代码
//颜色类(实现)
class Color {
public:
    virtual void applyColor() = 0;
    virtual ~Color() {}
};

//红色(具体实现)
class Red :public Color {
public:
    virtual void applyColor() override {
        cout << "Apply red color." << endl;
    }
};

//蓝色(具体实现)
class Blue :public Color {
public:
    virtual void applyColor() override {
        cout << "Apply blue color." << endl;
    }
};

//形状类(抽象)
class Shape {
protected:
    Color* color;
public:
    Shape(Color* c) :color(c) {}
    virtual void draw() = 0;
    virtual ~Shape() {
        delete color;
    }
};

//圆形(扩展抽象)
class Circle :public Shape {
public:
    using Shape::Shape;
    virtual void draw() override {
        color->applyColor();
        cout << "Drawing a circle." << endl;
    }
};

//矩形(扩展抽象)
class Rectangle :public Shape {
public:
    using Shape::Shape;
    virtual void draw() override {
        color->applyColor();
        cout << "Drawing a rectangle." << endl;
    }
};

测试代码:

cpp 复制代码
Color* red = new Red();
Shape* circle = new Circle(red);
circle->draw();
Color* blue = new Blue();
Shape* rect = new Rectangle(blue);
rect->draw();
delete circle;
delete rect;

输出结果:

bash 复制代码
Apply red color.
Drawing a circle.
Apply blue color.
Drawing a rectangle.

二、享元模式

1.定义

运用共享技术有效地支持大量细粒度的对象。

享元模式能够共享已存在的对象实例,而不是在需要时每次都创建新的对象实例,从而避免大量重复对象的开销。

2.组成

  • 抽象享元:作为所有具体享元类的基类,定义公共接口。
  • 具体享元:实现抽象享元类规定的接口,同时存储内部状态。并非所有的具体享元类都需要被共享。
  • 享元工厂:维护一个享元池,负责创建和管理享元对象。当需要享元对象时,工厂会提供一个现有的实例或创建一个新的实例。

3.示例

cpp 复制代码
//抽象享元
class Flyweight {
public:
    virtual void display() = 0;
    virtual ~Flyweight() {}
};

//字符样式(具体享元)
class CharStyle :public Flyweight {
private:
    string font;
    int size;
    string color;
public:
    CharStyle(string f, int s, string c):
        font(f), size(s), color(c) {}
    virtual void display() override {
        cout << "Font-" << font << ",Size-";
        cout << size << ",Color-" << color << endl;
    }
};

//享元工厂
class FlyweightFactory {
private:
    unordered_map<string, CharStyle*> styleMap;
public:
    CharStyle* getStyle(string f, int s, string c) {
        string key = f + to_string(s) + c;
        if (styleMap.find(key) == styleMap.end()) {
            cout << "创建新字符样式:" << endl;
            styleMap[key] = new CharStyle(f, s, c);
        }
        else {
            cout << "字符样式已存在:" << endl;
        }
        return styleMap[key];
    }
    ~FlyweightFactory() {
        for (auto& [x, y] : styleMap)
            delete y;
    }
};

测试代码:

cpp 复制代码
FlyweightFactory* factory = new FlyweightFactory();
Flyweight* style1 = factory->getStyle("Arial", 12, "Black");
style1->display();
Flyweight* style2 = factory->getStyle("Times New Roman", 14, "Blue");
style2->display();
Flyweight* style3 = factory->getStyle("Arial", 12, "Black");
style3->display();
delete factory;

输出结果:

bash 复制代码
创建新字符样式:
Font-Arial,Size-12,Color-Black
创建新字符样式:
Font-Times New Roman,Size-14,Color-Blue
字符样式已存在:
Font-Arial,Size-12,Color-Black

三、外观模式

1.定义

为子系统中的一组接口提供一个一致的界面, 外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

外观模式将多个子系统的功能封装起来,对外提供一个统一的接口。客户端只需要与外观类进行交互,而不需要与子系统类交互,从而降低了客户端与子系统之间的耦合度。

2.组成

  • 子系统:子系统可以是一组相互关联的类,它们共同实现一个或多个功能。
  • 外观:提供一个简化的接口,用于访问子系统中的功能。
  • 客户端:使用外观类提供的接口来访问子系统的功能,无需了解子系统的具体实现。

3.示例

cpp 复制代码
//厨房子系统
class Kitchen {
public:
    void cookFood(const string& dish) {
        cout << "厨房正在制作: " << dish << endl;
    }
};

//饮料机子系统
class BeverageMachine {
public:
    void makeBeverage(string beverage) {
        cout << "饮料机正在制作: " << beverage << endl;
    }
};

//结账子系统
class Payment {
public:
    void processPayment(double amount) {
        cout << "结账系统正在处理: " << amount << "$" << endl;
    }
};

//服务员(外观)
class Waiter {
private:
    Kitchen* kitchen;
    BeverageMachine* beverageMachine;
    Payment* payment;
public:
    void serveCustomer(string dish, string beverage, double amount) {
        kitchen->cookFood(dish);
        beverageMachine->makeBeverage(beverage);
        payment->processPayment(amount);
        cout << "顾客的餐饮已准备好,支付已处理。" << endl;
    }
};

测试代码:

cpp 复制代码
Waiter* waiter = new Waiter();
waiter->serveCustomer("汉堡", "可乐", 20.0);
delete waiter;

输出结果:

bash 复制代码
厨房正在制作: 汉堡
饮料机正在制作: 可乐
结账系统正在处理: 20$
顾客的餐饮已准备好,支付已处理。

四、状态模式

1.定义

允许一个对象在其内部状态改变时改变它的行为。

状态模式通过将对象的状态封装到不同的状态类中,使得对象的行为可以根据其内部状态的变化而动态改变,而不是通过大量的条件判断语句来实现。

2.组成

  • 抽象状态:定义一个接口,用于封装特定状态下的行为。
  • 具体状态:对应环境类的不同状态,用于实现不同状态下环境类应有的行为。
  • 环境:定义客户端感兴趣的接口,同时维护一个具体状态类的实例,这个实例代表当前对象的状态。

3.示例

cpp 复制代码
class MobilePhone;

//电量(抽象状态类)
class PowerState {
public:
    virtual void handleApp(MobilePhone* phone) = 0;
};

//电量充足状态(具体状态类)
class Full : public PowerState {
public:
    virtual void handleApp(MobilePhone* phone) override;
};

//电量中等状态(具体状态类)
class Midium :public PowerState {
public:
    virtual void handleApp(MobilePhone* phone) override;
};

//电量低状态(具体状态类)
class Low :public PowerState {
public:
    virtual void handleApp(MobilePhone* phone) override;
};

//电量耗尽状态(具体抽象类)
class None :public PowerState {
public:
    virtual void handleApp(MobilePhone* phone) override;
};

//手机(环境类)
class MobilePhone {
private:
    int power;
    PowerState* state;
public:
    MobilePhone() :state(new Full()), power(100) {}
    ~MobilePhone() {
        delete state;
    }
    void setState(PowerState* s) {
        if (state) {
            delete state;
        }
        state = s;
    }
    void startApp() {
        state->handleApp(this);
    }
    void setPower(unsigned int p) {
        power = p;
    }
    int getPower() {
        return power;
    }
};

void Full::handleApp(MobilePhone* phone) {
    int power = phone->getPower();
    if (power <= 100 && power >= 60) {
        cout << "当前电量:" << power << "%" << endl;
        cout << "电量充足,应用正常启动。" << endl;
    }
    else {
        phone->setState(new Midium());
        phone->startApp();
    }
}

void Midium::handleApp(MobilePhone* phone) {
    int power = phone->getPower();
    if (power < 60 && power >= 20) {
        cout << "当前电量:" << power << "%" << endl;
        cout << "电量中等,请注意电量消耗。" << endl;
    }
    else {
        phone->setState(new Low());
        phone->startApp();
    }
}

void Low::handleApp(MobilePhone* phone) {
    int power = phone->getPower();
    if (power < 20 && power > 1) {
        cout << "当前电量:" << power << "%" << endl;
        cout << "电量低,启动应用可能影响手机运行, 部分后台应用已关闭。" << endl;
    }
    else {
        phone->setState(new None());
        phone->startApp();
    }
}

void None::handleApp(MobilePhone* phone) {
    int power = phone->getPower();
    if (power <= 1 && power >= 0) {
        cout << "当前电量:" << power << "%" << endl;
        cout << "手机已关机,无法启动应用。" << endl;
    }
}

测试代码:

cpp 复制代码
MobilePhone* phone = new MobilePhone();
int powers[]{ 90, 50, 10, 0 };
for (auto x : powers) {
    phone->setPower(x);
    phone->startApp();
}
delete phone;

输出结果:

bash 复制代码
当前电量:90%
电量充足,应用正常启动。
当前电量:50%
电量中等,请注意电量消耗。
当前电量:10%
电量低,启动应用可能影响手机运行, 部分后台应用已关闭。
当前电量:0%
手机已关机,无法启动应用。
相关推荐
唔知小罗几秒前
网络编程UDP—socket实现(C++)
网络·c++·udp
知星小度S1 分钟前
今天你学C++了吗?——C++中的模板
开发语言·c++
Dream it possible!9 分钟前
LeetCode 热题 100_LRU 缓存(35_146_中等_C++)(哈希表 + 双向链表)(构造函数声明+初始化列表=进行变量初始化和赋值)
c++·leetcode·缓存
wkd_0071 小时前
【开源库 | xlsxio】C/C++读写.xlsx文件,xlsxio 在 Linux(Ubuntu18.04)的编译、交叉编译
c语言·c++·xlsxio·c语言读写xlsx·c++读写xlsx·xlsxio交叉编译
捕鲸叉2 小时前
C++软件设计模式之类型模式和对象型模式
开发语言·c++·设计模式
诸葛悠闲3 小时前
设计模式——组合模式
设计模式·组合模式
诸葛悠闲3 小时前
设计模式——装饰模式
设计模式
西岭千秋雪_3 小时前
设计模式の中介者&发布订阅&备忘录模式
java·观察者模式·设计模式·中介者模式·备忘录模式
捕鲸叉3 小时前
C++软件设计模式之代理(Proxy)模式
c++·设计模式
思忖小下3 小时前
梳理你的思路(从OOP到架构设计)_介绍GoF设计模式
设计模式·架构·eit