C++设计模式之享元模式

主要解决

在有大量相似对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。

优点

大大减少对象的创建,降低系统的内存,使效率提高。

缺点

提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱

关键代码

  • Flyweight(享元):定义一个接口,通过它可以接收并作用于外部状态;
  • Concrete Flyweight(具体享元):实现Flyweight接口,并为内部状态增加存储空间;
  • Unshared Concrete Flyweight(非共享具体享元):由于客户端需要,享元对象不能进行共享的子类;
  • Flyweight Factory(享元工厂):用于创建和管理Flyweight对象,可以通过享元工厂实现对象池。
    请添加图片描述

请添加图片描述

示例

我们再以数据库连接为例,来进一步说明享元模式的使用场景。

假设我们正在编写一个数据库应用程序,其中有许多不同的数据库连接对象。在此过程中,由于每个连接都需要打开和关闭,并且提供的服务通常只需要少量的属性(如主机名、用户名和密码等),因此我们可以使用享元模式来共享这些属性,从而达到优化性能的目的。

首先,我们定义一个抽象的Database类作为所有数据库连接对象的基类,并在其中定义共同的属性和方法(如打开连接和关闭连接等)。然后,通过实现Database接口,我们可以创建多个ConcreteDatabase类(例如MySQL和Oracle),并为内部状态增加存储空间。

class Database {
public:
    virtual void open() = 0;
    virtual void close() = 0;

protected:
    string host_;
    string username_;
    string password_;
};

class MySQL : public Database {
public:
    MySQL(string host, string username, string password) {
        this->host_ = host;
        this->username_ = username;
        this->password_ = password;
    }

    void open() override {
        cout << "Open a MySQL database connection at " << this->host_ 
             << " with username " << this->username_ << endl;
    }

    void close() override {
        cout << "Close the MySQL database connection at " << this->host_ << endl;
    }
};

class Oracle : public Database {
public:
    Oracle(string host, string username, string password) {
        this->host_ = host;
        this->username_ = username;
        this->password_ = password;
    }

    void open() override {
        cout << "Open an Oracle database connection at " << this->host_ 
             << " with username " << this->username_ << endl;
    }

    void close() override {
        cout << "Close the Oracle database connection at " << this->host_ << endl;
    }
};

接下来我们再定义一个DatabaseFactory类来实现享元工厂,以便创建和管理不同的Database对象,其中,DatabaseFactory的内部存储了一个SharePool对象,用于存放所有的共享Database对象,并通过getConnection方法对所有请求进行处理。如果请求对象已存在,直接返回共享对象;否则,创建新的对象并将其加入到SharePool中进行管理。

class SharePool {
public:
    static shared_ptr<Database> getConnection(string host, string username, string password) {
        auto key = host + username + password;
        auto it = dbMap_.find(key);
        if (it != dbMap_.end())
            return it->second;
        auto shareDb = make_shared<MySQL>(host, username, password);
        dbMap_[key] = shareDb;
        return shareDb;
    }

    static void clear() {
        dbMap_.clear();
    }

private:
    static map<string, shared_ptr<Database>> dbMap_;
};

map<string, shared_ptr<Database>> SharePool::dbMap_;

class DatabaseFactory {
public:
    static shared_ptr<Database> getConnection(string host, string username, string password) {
        return SharePool::getConnection(host, username, password);
    }
};

最后,在客户端中,我们可以通过DatabaseFactory来获取具体的MySQL或Oracle等数据库连接对象,并将共同的属性作为参数传入。

int main() {
    auto conn1 = DatabaseFactory::getConnection("localhost", "root", "pwd");
    conn1->open();
    //do some work...
    conn1->close();

    auto conn2 = DatabaseFactory::getConnection("localhost", "root", "pwd");
    conn2->open();
    //do some work...
    conn2->close();
    // conn2与conn1是同一个对象

    return 0;
}

参考

https://blog.csdn.net/u012011079/article/details/126033261
https://pythonjishu.com/yuqelkqbsifbaza/
https://www.runoob.com/design-pattern/flyweight-pattern.html

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值