设计模式
设计原则:单一职责原则、开放封闭原则、里氏替换原则、最少知识原则、接口隔离原则、依赖倒置原则。
[注]:本系列为个人学习用,主要介绍设计模式相关知识。之后的示意图中借用了菜鸟教程
中的结构图,代码为个人原创并且全部可以运行。
一:单例模式
单例模式
c++的单例模式,实际上是一种管理全局变量和静态函数的设计模式。
1. 饿汉式单例
-
特点
- 在类加载时就创建实例,线程安全。
- 类一加载,单例就被实例化,浪费了内存(如果实例始终未被使用)。
-
实现步骤
- 将构造函数声明为私有,防止外部创建实例。
- 创建一个静态实例,并在类加载时初始化。
- 提供一个静态方法返回实例。
2. 懒汉式单例
-
特点
- 在第一次调用获取实例时才创建实例,避免了类加载时立即初始化的问题。
- 需要注意线程安全问题,如果多个线程同时调用,可能会创建多个实例。
-
实现步骤
- 将构造函数声明为私有。
- 创建一个静态实例变量,但不初始化。
- 在 getInstance 方法中判断是否已创建实例,如果没有则创建。
3. 双重检查锁
-
特点
- 在
懒汉式
基础上增加了线程安全的优化。 - 通过双重判断和加锁,保证实例只被创建一次,同时减少了锁的性能开销。
- 在
-
实现步骤
- 外层判断是否为 nullptr,避免进入锁。
- 内层加锁,并再次判断是否需要初始化。
4. 静态内部类
-
特点
- 基于 Java 的类加载机制,利用静态内部类的特点实现延迟加载。
- 静态内部类在被调用时才会加载,并初始化单例。
-
实现步骤
- 外部类构造函数私有。
- 定义一个静态内部类,内部类中包含单例实例。
- 提供一个静态方法调用内部类实例。
5. 枚举
-
特点
- 最简洁且最安全的实现方式,避免了序列化和反射问题。
- 通过枚举的唯一性保证单例。
-
实现步骤
- 定义一个枚举类型,其中包含单例实例。
- 提供方法访问该实例。
简单工厂模式(静态工厂模式)
工厂可以根据参数的不同返回不同的产品
1. 组成
-
Factory(工厂):核心部分,负责实现创建所有产品的内部逻辑,工厂类可以被外界直接调用,创建所需对象
工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了 -
Product(抽象类产品):工厂类所创建的所有对象的父类,封装了产品对象的公共方法,所有的具体产品为其子类对象
-
ProductA、ProductB…(具体产品):简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例。它要实现抽象产品中声明的抽象方法
#include <bits/stdc++.h>
using namespace std;
// 以披萨为例,创建披萨的工厂类
// 假设有三种披萨,分别为:奶酪披萨、香肠披萨、海鲜披萨
class Pizza
{
public:
virtual void prepare() = 0;
virtual void bake() = 0;
virtual void cut() = 0;
virtual void box() = 0;
virtual ~Pizza() {}
};
class CheesePizza : public Pizza
{
public:
void prepare() override
{
cout << "Prepare cheese pizza" << endl;
}
void bake() override
{
cout << "Bake cheese pizza" << endl;
}
void cut() override
{
cout << "Cut cheese pizza" << endl;
}
void box() override
{
cout << "Box cheese pizza" << endl;
}
};
class PepperoniPizza : public Pizza
{
public:
void prepare() override
{
cout << "Prepare pepperoni pizza" << endl;
}
void bake() override
{
cout << "Bake pepperoni pizza" << endl;
}
void cut() override
{
cout << "Cut pepperoni pizza" << endl;
}
void box() override
{
cout << "Box pepperoni pizza" << endl;
}
};
class SeafoodPizza : public Pizza
{
public:
void prepare() override
{
cout << "Prepare seafood pizza" << endl;
}
void bake() override
{
cout << "Bake seafood pizza" << endl;
}
void cut() override
{
cout << "Cut seafood pizza" << endl;
}
void box() override
{
cout << "Box seafood pizza" << endl;
}
};
class PizzaFactory
{
public:
static Pizza *createPizza(const string &type)
{
if (type == "cheese")
{
return new CheesePizza();
}
else if (type == "pepperoni")
{
return new PepperoniPizza();
}
else if (type == "seafood")
{
return new SeafoodPizza();
}
else
{
cout << "Unknown pizza type" << endl;
return nullptr;
}
}
};
int main()
{
string pizzaType;
cout << "Enter pizza type (cheese/pepperoni/seafood): ";
cin >> pizzaType;
Pizza *pizza = PizzaFactory::createPizza(pizzaType);
if (pizza != nullptr)
{
pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box();
delete pizza;
}
return 0;
}
缺点
-
违反开放-封闭原则(OCP): 当需要新增一种产品时,需要修改工厂类的源代码来添加新的产品类型,这违反了开放-封闭原则。每次修改都会导致工厂类的变化,可能引发其他代码的修改和重新测试,增加了维护成本和风险。
-
单一职责原则问题: 简单工厂模式中的工厂类负责创建不同类型的产品,导致工厂类的职责不够单一,违反了单一职责原则。随着产品类型的增加,工厂类的代码逐渐变得臃肿,难以维护和理解。
-
如果需要新增一种产品类型,除了要修改工厂类的代码外,还可能需要修改客户端代码来传递正确的参数类型。这种做法不够灵活,难以应对产品类型的频繁变化。
-
虽然简单工厂模式封装了对象的创建过程,但它也隐藏了产品的具体创建细节,导致客户端无法直接控制对象的创建过程,无法灵活地定制对象的创建方式。
工厂模式
- 工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,也就是说工厂模式让实例化推迟到子类。
#include <bits/stdc++.h>
using namespace std;
class Pizza
{
public:
virtual void prepare() = 0;
virtual void bake() = 0;
virtual void cut() = 0;
virtual void box() = 0;
virtual ~Pizza() {}
};
class CheesePizza : public Pizza
{
public:
void prepare()
{
cout << "Preparing cheese pizza" << endl;
}
void bake()
{
cout << "Baking cheese pizza" << endl;
}
void cut()
{
cout << "Cutting cheese pizza" << endl;
}
void box()
{
cout << "Boxing cheese pizza" << endl;
}
};
class PepperoniPizza : public Pizza
{
public:
void prepare()
{
cout << "Preparing pepperoni pizza" << endl;
}
void bake()
{
cout << "Baking pepperoni pizza" << endl;
}
void cut()
{
cout << "Cutting pepperoni pizza" << endl;
}
void box()
{
cout << "Boxing pepperoni pizza" << endl;
}
};
class SeafoodPizza : public Pizza
{
public:
void prepare()
{
cout << "Preparing seafood pizza" << endl;
}
void bake()
{
cout << "Baking seafood pizza" << endl;
}
void cut()
{
cout << "Cutting seafood pizza" << endl;
}
void box()
{
cout << "Boxing seafood pizza" << endl;
}
};
class PizzaFactory
{
public:
virtual Pizza *createPizza() = 0;
virtual ~PizzaFactory() {}
};
class CheesePizzaFactory : public PizzaFactory
{
public:
Pizza *createPizza() override
{
return new CheesePizza();
}
};
class PepperoniPizzaFactory : public PizzaFactory
{
public:
Pizza *createPizza() override
{
return new PepperoniPizza();
}
};
class SeafoodPizzaFactory : public PizzaFactory
{
public:
Pizza *createPizza() override
{
return new SeafoodPizza();
}
};
int main()
{
string pizzaType;
cout << "Enter pizza type (cheese/pepperoni/seafood): ";
cin >> pizzaType;
PizzaFactory *factory = nullptr;
if (pizzaType == "cheese")
{
factory = new CheesePizzaFactory();
}
else if (pizzaType == "pepperoni")
{
factory = new PepperoniPizzaFactory();
}
else if (pizzaType == "seafood")
{
factory = new SeafoodPizzaFactory();
}
else
{
cout << "Unknown pizza type" << endl;
return 1;
}
Pizza *pizza = factory->createPizza();
if (pizza != nullptr)
{
pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box();
delete pizza;
}
delete factory;
return 0;
}
抽象工厂模式
抽象工厂的思想是:把有关联关系的,属于一个产品簇的所有产品创建的接口函数,放在一个抽象工厂里面 AbstractFactory,派生类(具体产品的工厂)应该负责创建该产品簇里面所有的产品。
#include <bits/stdc++.h>
using namespace std;
// 披萨基类
class Pizza
{
public:
virtual void prepare() = 0;
virtual void bake() = 0;
virtual void cut() = 0;
virtual void box() = 0;
virtual ~Pizza() {}
};
// 奶酪披萨类
class CheesePizza : public Pizza
{
public:
void prepare() override
{
cout << "Preparing cheese pizza" << endl;
}
void bake() override
{
cout << "Baking cheese pizza" << endl;
}
void cut() override
{
cout << "Cutting cheese pizza" << endl;
}
void box() override
{
cout << "Boxing cheese pizza" << endl;
}
};
// 香肠披萨类
class PepperoniPizza : public Pizza
{
public:
void prepare() override
{
cout << "Preparing pepperoni pizza" << endl;
}
void bake() override
{
cout << "Baking pepperoni pizza" << endl;
}
void cut() override
{
cout << "Cutting pepperoni pizza" << endl;
}
void box() override
{
cout << "Boxing pepperoni pizza" << endl;
}
};
// 海鲜披萨类
class SeafoodPizza : public Pizza
{
public:
void prepare() override
{
cout << "Preparing seafood pizza" << endl;
}
void bake() override
{
cout << "Baking seafood pizza" << endl;
}
void cut() override
{
cout << "Cutting seafood pizza" << endl;
}
void box() override
{
cout << "Boxing seafood pizza" << endl;
}
};
// 汉堡基类
class Hamburger
{
public:
virtual void prepare() = 0;
virtual void cook() = 0;
virtual void cut() = 0;
virtual void pack() = 0;
virtual ~Hamburger() {}
};
// 奶酪汉堡类
class CheeseHamburger : public Hamburger
{
public:
void prepare() override
{
cout << "Preparing cheese hamburger" << endl;
}
void cook() override
{
cout << "Cooking cheese hamburger" << endl;
}
void cut() override
{
cout << "Cutting cheese hamburger" << endl;
}
void pack() override
{
cout << "Packing cheese hamburger" << endl;
}
};
// 香肠汉堡类
class PepperoniHamburger : public Hamburger
{
public:
void prepare() override
{
cout << "Preparing pepperoni hamburger" << endl;
}
void cook() override
{
cout << "Cooking pepperoni hamburger" << endl;
}
void cut() override
{
cout << "Cutting pepperoni hamburger" << endl;
}
void pack() override
{
cout << "Packing pepperoni hamburger" << endl;
}
};
// 海鲜汉堡类
class SeafoodHamburger : public Hamburger
{
public:
void prepare() override
{
cout << "Preparing seafood hamburger" << endl;
}
void cook() override
{
cout << "Cooking seafood hamburger" << endl;
}
void cut() override
{
cout << "Cutting seafood hamburger" << endl;
}
void pack() override
{
cout << "Packing seafood hamburger" << endl;
}
};
// 抽象工厂基类
class AbstractFactory
{
public:
virtual Pizza *createPizza() = 0;
virtual Hamburger *createHamburger() = 0;
virtual ~AbstractFactory() {}
};
// 奶酪披萨和奶酪汉堡工厂类
class CheeseFactory : public AbstractFactory
{
public:
Pizza *createPizza() override
{
return new CheesePizza();
}
Hamburger *createHamburger() override
{
return new CheeseHamburger();
}
};
// 香肠披萨和香肠汉堡工厂类
class PepperoniFactory : public AbstractFactory
{
public:
Pizza *createPizza() override
{
return new PepperoniPizza();
}
Hamburger *createHamburger() override
{
return new PepperoniHamburger();
}
};
// 海鲜披萨和海鲜汉堡工厂类
class SeafoodFactory : public AbstractFactory
{
public:
Pizza *createPizza() override
{
return new SeafoodPizza();
}
Hamburger *createHamburger() override
{
return new SeafoodHamburger();
}
};
int main()
{
string productType;
cout << "Enter product type (cheese/pepperoni/seafood): ";
cin >> productType;
AbstractFactory *factory = nullptr;
if (productType == "cheese")
{
factory = new CheeseFactory();
}
else if (productType == "pepperoni")
{
factory = new PepperoniFactory();
}
else if (productType == "seafood")
{
factory = new SeafoodFactory();
}
else
{
cout << "Unknown product type" << endl;
return 1;
}
Pizza *pizza = factory->createPizza();
if (pizza != nullptr)
{
pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box();
delete pizza;
}
Hamburger *hamburger = factory->createHamburger();
if (hamburger != nullptr)
{
hamburger->prepare();
hamburger->cook();
hamburger->cut();
hamburger->pack();
delete hamburger;
}
delete factory;
return 0;
}