设计模式
文章目录
- 设计模式
-
- 创建型模式
-
- [单例模式 [1-小明的购物车](https://kamacoder.com/problempage.php?pid=1074)](#单例模式 1-小明的购物车)
- [工厂模式 [2-积木工厂](https://kamacoder.com/problempage.php?pid=1076)](#工厂模式 2-积木工厂)
- [抽象⼯⼚模式 [3-家具工厂](https://kamacoder.com/problempage.php?pid=1077)](#抽象⼯⼚模式 3-家具工厂)
- [建造者模式 [4-⾃⾏⻋加⼯](https://kamacoder.com/problempage.php?pid=1077)](#建造者模式 4-⾃⾏⻋加⼯)
- [原型模式 [5-矩形原型](https://kamacoder.com/problempage.php?pid=1083)](#原型模式 5-矩形原型)
创建型模式
单例模式 1-小明的购物车
单例模式是⼀种创建型设计模式, 它的核⼼思想是保证⼀个类只有⼀个实例,并提供⼀个全局访问点来访问这个实
例。
-
只有⼀个实例的意思是,在整个应⽤程序中(进程),只存在该类的⼀个实例对象,⽽不是创建多个相同类型的对象。
-
全局访问点的意思是,为了让其他类能够获取到这个唯⼀实例,该类提供了⼀个全局访问点(通常是⼀个静态 ⽅法),通过这个⽅法就能获得实例
#include <iostream>
#include <unordered_map>
#include <vector>
#include<mutex>
#include<atomic>class ShoppingCartManager {
private:
std::unordered_map<std::string, int> cart;
std::vectorstd::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;
}