23种设计模式——创建型模式

设计模式

创建型模式

单例模式 1-小明的购物车

单例模式是⼀种创建型设计模式, 它的核⼼思想是保证⼀个类只有⼀个实例,并提供⼀个全局访问点来访问这个实
例。

  • 只有⼀个实例的意思是,在整个应⽤程序中(进程),只存在该类的⼀个实例对象,⽽不是创建多个相同类型的对象。
  • 全局访问点的意思是,为了让其他类能够获取到这个唯⼀实例,该类提供了⼀个全局访问点(通常是⼀个静态 ⽅法),通过这个⽅法就能获得实例
#include <iostream>
#include <unordered_map>
#include <vector>
#include<mutex>
#include<atomic>
  
  
class ShoppingCartManager {
private:
    std::unordered_map<std::string, int> cart;
    std::vector<std::string> order; // 保持顺序
  
    // 私有构造函数
    ShoppingCartManager() {}
     
    static std::mutex m_mutex;
    //static ShoppingCartManager* m_cart;
    static std::atomic<ShoppingCartManager*> m_atomic; //使用原子变量将对象指针保存
    
public:
    // 获取购物车实例
    static ShoppingCartManager* getInstance() {
        ShoppingCartManager* m_cart = m_atomic.load();
        if (m_cart == nullptr) {
            m_mutex.lock();
            m_cart = m_atomic.load();
            if (m_cart == nullptr) {
                m_cart = new ShoppingCartManager;
                m_atomic.store(m_cart); //保存对象指针
            }
            m_mutex.unlock();
        }
        return m_cart;
    }
  
    // 添加商品
    void addToCart(const std::string& itemName, int quantity) {
        if (cart.find(itemName) == cart.end()) { //如果cart里面没有该货物
            order.push_back(itemName); //注意这里是order,为了使得货物和数量能对齐
        }
        cart[itemName] += quantity;
    }
  
    // 查看商品
    void viewCart() const {
        for (const auto& itemName : order) { //这里按照顺序读取货物,保证有序输出;若只用unordered_map,无法保证有序
            std::cout << itemName << " " << cart.at(itemName) << std::endl;
        }
    }
};
  
//ShoppingCartManager* ShoppingCartManager::m_cart = nullptr;
std::atomic<ShoppingCartManager*> ShoppingCartManager::m_atomic;
std::mutex ShoppingCartManager::m_mutex;
  
int main() {
    std::string itemName;
    int quantity;
  
    ShoppingCartManager* cart = ShoppingCartManager::getInstance();
  
    while (std::cin >> itemName >> quantity) {
        cart->addToCart(itemName, quantity);
    }
  
    cart->viewCart();
  
    return 0;
}

使用静态局部变量保证多线程下的资源安全

工厂模式 2-积木工厂

⼯⼚⽅法模式也是⼀种创建型设计模式,简单⼯⼚模式只有⼀个⼯⼚类,负责创建所有产品,如果要添加新的产品,通常需要修改⼯⼚类的代码。⽽⼯⼚⽅法模式引⼊了抽象⼯⼚和具体⼯⼚的概念,每个具体⼯⼚只负责创建⼀个具体产品,添加新的产品只需要添加新的⼯⼚类⽽⽆需修改原来的代码,这样就使得产品的⽣产更加灵活,⽀持扩展,符合开闭原则。
⼯⼚⽅法模式分为以下⼏个⻆⾊:
抽象⼯⼚:⼀个接⼝,包含⼀个

  • 抽象的⼯⼚⽅法(⽤于创建产品对象)。
  • 具体⼯⼚:实现抽象⼯⼚接⼝,创建具体的产品。
  • 抽象产品:定义产品的接⼝。
  • 具体产品:实现抽象产品接⼝,是⼯⼚创建的对象。
// 表驱动 + lambda 表达式

#include<iostream>
#include<bits/stdc++.h>

using namespace std;

class Shape {
public:
    virtual void show() = 0;
};

class Circle : public Shape {
public:
    void show() {
        cout << "Circle Block" << endl;
    }
};

class Square : public Shape {
public:
    void show () {
        cout << "Square Block" << endl;
    }
};

class ShapeFactory {
public:
    virtual Shape* produce() = 0;
};

class CircleFactory : public ShapeFactory {
public:
    Shape* produce() {
        return new Circle();
    }
};

class SquareFactory : public ShapeFactory {
public:
    Shape* produce() {
        return new Square();
    }
};

unordered_map<string, function<ShapeFactory*()>> m {
    {"Circle", [](){ return new CircleFactory();}},
    {"Square", [](){ return new SquareFactory();}},
};

class BlocksFactory {
public:
    vector<Shape*> blocks;
    
    void CreateBlocks(string& type, int count) {
        ShapeFactory* sf = m[type]();
        Shape* s = sf -> produce();
        for (int i = 0; i < count; i++) {
            blocks.push_back(s);
        }
    }

    void Print() {
        for (const auto& s : blocks) {
            s -> show();
        }

    }
};



int main() {
    int produceTime;
    cin >> produceTime;

    string type;
    int count;
    BlocksFactory* bf = new BlocksFactory();
    for (int i = 0; i < produceTime; i++) {
        cin >> type >> count;
        bf->CreateBlocks(type, count);
    }
    bf->Print();

    return 0;
}

抽象⼯⼚模式 3-家具工厂

抽象⼯⼚模式包含多个抽象产品接⼝,多个具体产品类,⼀个抽象⼯⼚接⼝和多个具体⼯⼚,每个具体⼯⼚负责创建⼀组相关的产品。

  • 抽象产品接⼝ AbstractProduct : 定义产品的接⼝,可以定义多个抽象产品接⼝,⽐如说沙发、椅⼦、茶⼏都是抽象产品。
  • 具体产品类 ConcreteProduct : 实现抽象产品接⼝,产品的具体实现,古典⻛格和沙发和现代⻛格的沙发都是具体产品。
  • 抽象⼯⼚接⼝AbstractFactory : 声明⼀组⽤于创建产品的⽅法,每个⽅法对应⼀个产品。
  • 具体⼯⼚类 ConcreteFactory : 实现抽象⼯⼚接⼝,,负责创建⼀组具体产品的对象,在本例中,⽣产古典⻛格的⼯⼚和⽣产现代⻛格的⼯⼚都是具体实例.
#include <iostream>
#include <string>
#include <unordered_map>
#include <functional>

using namespace std;


class Sofa {
public:
    virtual void info() = 0;
};

class ModernSofa : public Sofa {
public:
    void info() override {
        cout << "modern sofa" << endl;
    };
};

class ClassicalSofa : public Sofa {
public:
    void info() override {
        cout << "classical sofa" << endl;
    };
};

class Chair {
public:
    virtual void info() = 0;
};

class ModernChair : public Chair {
public:
    void info() override {
      cout << "modern chair" << endl;
    };
};

class ClassicalChair : public Chair {
public:
    void info() override {
      cout << "classical chair" << endl;
    };
};

class Factory {
public:
    virtual Sofa *buildSofa() = 0;
    virtual Chair *buildChair() = 0;
};

class ModernFactory : public Factory {
public:
    Sofa *buildSofa() override
    {
        return new ModernSofa();
    }
    
    Chair *buildChair() override
    {
        return new ModernChair();
    }
};

class ClassicalFactory : public Factory {
public:
    Sofa *buildSofa() override
    {
        return new ClassicalSofa();
    }
    
    Chair *buildChair() override
    {
        return new ClassicalChair();
    }
};

unordered_map<string, function<Factory*()>> factoryTable {
    {"modern", [](){ return new ModernFactory(); }},
    {"classical", [](){ return new ClassicalFactory(); }}
};

int main()
{
    int loop;
    cin >> loop;
    
    string type;
    while (loop--)
    {
        cin >> type;
        Factory *f = factoryTable[type]();
        Chair *c = f->buildChair();
        Sofa *s = f->buildSofa();
        c->info();
        s->info();
    }
    
    return 0;
}

建造者模式 4-⾃⾏⻋加⼯

建造者模式(也被成为⽣成器模式),是⼀种创建型设计模式,软件开发过程中有的时候需要创建很复杂的对象,⽽建造者模式的主要思想是将对象的构建过程分为多个步骤,并为每个步骤定义⼀个抽象的接⼝。具体的构建过程由实现了这些接⼝的具体建造者类来完成。同时有⼀个指导者类负责协调建造者的⼯作,按照⼀定的顺序或逻辑来执⾏构建步骤,最终⽣成产品。

  • 产品Product:被构建的复杂对象, 包含多个组成部分。
  • 抽象建造者 Builder : 定义构建产品各个部分的抽象接⼝和⼀个返回复杂产品的⽅法
  • 具体建造者 getResult Concrete Builder :实现抽象建造者接⼝,构建产品的各个组成部分,并提供⼀个⽅法返回最终的产品。
  • 指导者 Director :调⽤具体建造者的⽅法,按照⼀定的顺序或逻辑来构建产品。

使⽤建造者模式有下⾯⼏处优点:

  • 使⽤建造者模式可以将⼀个复杂对象的构建与其表示分离,通过将构建复杂对象的过程抽象出来,可以使客户端代码与具体的构建过程解耦
  • 同样的构建过程可以创建不同的表示,可以有多个具体的建造者(相互独⽴),可以更加灵活地创建不同组合的对象
#include <iostream>
#include <string>
#include <unordered_map>
#include <functional>

using namespace std;


class Sofa {
public:
    virtual void info() = 0;
};

class ModernSofa : public Sofa {
public:
    void info() override {
        cout << "modern sofa" << endl;
    };
};

class ClassicalSofa : public Sofa {
public:
    void info() override {
        cout << "classical sofa" << endl;
    };
};

class Chair {
public:
    virtual void info() = 0;
};

class ModernChair : public Chair {
public:
    void info() override {
      cout << "modern chair" << endl;
    };
};

class ClassicalChair : public Chair {
public:
    void info() override {
      cout << "classical chair" << endl;
    };
};

class Factory {
public:
    virtual Sofa *buildSofa() = 0;
    virtual Chair *buildChair() = 0;
};

class ModernFactory : public Factory {
public:
    Sofa *buildSofa() override
    {
        return new ModernSofa();
    }
    
    Chair *buildChair() override
    {
        return new ModernChair();
    }
};

class ClassicalFactory : public Factory {
public:
    Sofa *buildSofa() override
    {
        return new ClassicalSofa();
    }
    
    Chair *buildChair() override
    {
        return new ClassicalChair();
    }
};

unordered_map<string, function<Factory*()>> factoryTable {
    {"modern", [](){ return new ModernFactory(); }},
    {"classical", [](){ return new ClassicalFactory(); }}
};

int main()
{
    int loop;
    cin >> loop;
    
    string type;
    while (loop--)
    {
        cin >> type;
        Factory *f = factoryTable[type]();
        Chair *c = f->buildChair();
        Sofa *s = f->buildSofa();
        c->info();
        s->info();
    }
    
    return 0;
}

原型模式 5-矩形原型

如果⼀个对象的创建过程⽐较复杂时(⽐如需要经过⼀系列的计算和资源消耗),那每次创建该对象都需要消耗资源,⽽通过原型模式就可以复制现有的⼀个对象来迅速创建/克隆⼀个新对象,不必关⼼具体的创建细节,可以降低对象创建的成本。
原型模式的基本结构
实现原型模式需要给【原型对象】声明⼀个克隆⽅法,执⾏该⽅法会创建⼀个当前类的新对象,并将原始对象中的成员变量复制到新⽣成的对象中,⽽不必实例化。并且在这个过程中只需要调⽤原型对象的克隆⽅法,⽽⽆需知道原型对象的具体类型。
原型模式包含两个重点模块:

  • 抽象原型接⼝ prototype : 声明⼀个克隆⾃身的⽅法
  • 具体原型类 ConcretePrototype : 实现 clone ⽅法,复制当前对象并返回⼀个新对象。在客户端代码中,可以声明⼀个具体原型类的对象,然后调⽤clone() ⽅法复制原对象⽣成⼀个新的对象
#include<iostream>
#include<string>
using namespace std;

class Prototype {
public:
    virtual Prototype* clone() = 0;
    virtual void print() = 0;
    virtual ~Prototype() {}
};

class Triangle : public Prototype{
private:
    string color;
    int width, height;
public:
    Triangle(const string& color, int width, int height)
        : color(color), width(width), height(height) {}

    Prototype* clone() override {
        return new Triangle(this->color, this->width, this->height);
    }
    
    void print() override {
        cout<<"Color: "<<this->color<<", Width: "<<this->width<<", Height: "<<this->height<<endl;
    }
};

int main(){
    int n;
    string color;
    int w,h;
    cin >> color >> w >> h;
    cin >> n;
    while(n--){

        Prototype* original = new Triangle(color, w, h);
        Prototype* cloned = original->clone();
        cloned->print();
        delete original;
        delete cloned;
    }
    return 0;
}

相关推荐

  1. 23设计模式——创建模式

    2024-06-10 09:40:04       9 阅读
  2. 23设计模式创建模式

    2024-06-10 09:40:04       15 阅读
  3. 23设计模式之结构模式

    2024-06-10 09:40:04       14 阅读
  4. 设计模式——23

    2024-06-10 09:40:04       31 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-10 09:40:04       8 阅读
  2. 【Python教程】压缩PDF文件大小

    2024-06-10 09:40:04       9 阅读
  3. 通过文章id递归查询所有评论(xml)

    2024-06-10 09:40:04       10 阅读

热门阅读

  1. 2024年6月10日--6月16日(渲染+ue独立游戏)

    2024-06-10 09:40:04       10 阅读
  2. Terminal Multiplexer的使用

    2024-06-10 09:40:04       9 阅读
  3. 什么情况下需要用到动态IP

    2024-06-10 09:40:04       6 阅读
  4. node-mysql中占位符?的使用

    2024-06-10 09:40:04       8 阅读
  5. 007 CentOS 7.9 apache-tomcat-9.0.89安装及配置

    2024-06-10 09:40:04       7 阅读
  6. 设计模式-策略模式

    2024-06-10 09:40:04       7 阅读
  7. 密码学及其应用——安全邮件、公钥密码学和PKI

    2024-06-10 09:40:04       8 阅读
  8. 语法、语义、语用与向量化

    2024-06-10 09:40:04       8 阅读
  9. 给gRPC增加负载均衡功能

    2024-06-10 09:40:04       8 阅读
  10. websocket发送数据

    2024-06-10 09:40:04       6 阅读
  11. Spring (49)OpenFeign

    2024-06-10 09:40:04       7 阅读