什么是设计模式
-
设计模式是什么
-
- 设计模式是指在软件开发中,经过验证的、用于解决在特定环境下、重复出现的、特定问题的解决方案。(解决问题的固定套路)
-
解决了什么问题
-
- 期望修改少量的代码,就可以适应需求的变化
23种设计模式
工厂模式
主要是对对象的创建进行了一个封装。让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
简单工厂
//产品
class Car {
public:
Car(string na) : name(na) {}
virtual void Show() = 0;
protected:
string name;
};
class BMW : public Car {
public:
BMW(string na) : Car(na) {}
void Show() override {
cout << "得到一辆宝马" << name << endl;
}
};
class AUDI : public Car {
public:
AUDI(string na) : Car(na) {}
void Show() override {
cout << "得到一辆奥迪" << name << endl;
}
};
//工厂
enum carType {
bmw,
audi
};
class SimpleFactory {
public:
Car* createCar(carType ct) {
switch (ct) {
case bmw:
return new BMW("x6");
case audi:
return new AUDI("a8");
}
return nullptr;
}
};
#include <memory> //智能指针
int main() {
unique_ptr<SimpleFactory> factory(new SimpleFactory());
unique_ptr<Car> car1(factory->createCar(bmw));
unique_ptr<Car> car2(factory->createCar(audi));
car1->Show();
car2->Show();
return 0;
}
优点:
- 一个调用者想创建一个对象,只要知道其名称就可以了;
- 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以;
- 屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
开-闭原则:
对扩展开发、对修改关闭;
也就是说,我们可以添加代码,但是添加代码的时候不能对现有的代码进行修改。
工厂方法
为了解决简单工厂的缺点。定义一个Factory基类,基类中定义一个纯虚函数(创建产品),之后定义派生类(具体产品的工厂)负责创建对应的产品。一个工厂创建一种产品。
//产品(同上)
...
//工厂
class Factory {
public:
virtual Car* createCar(string name) = 0;
};
//宝马工厂
class BMWFac : public Factory {
public:
Car* createCar(string name) override {
return new BMW(name);
}
};
//奥迪工厂
class AUDIFac : public Factory {
public:
Car* createCar(string name) override {
return new AUDI(name);
}
};
int main() {
unique_ptr<Factory> bmwfactory(new BMWFac());
unique_ptr<Factory> audifactory(new AUDIFac());
unique_ptr<Car> car1(bmwfactory->createCar("x6"));
unique_ptr<Car> car2(audifactory->createCar("a8"));
car1->Show();
car2->Show();
return 0;
}
缺点:
宝马工厂不应该只卖一种商品,而我们的宝马工厂BmwFac里面只有一个createCar方法,如果想要添加产品的话,就需要增加新的类。但是这些产品其实都应该在一个BmwFac工厂里面。这才是现实的逻辑,另外,工厂类太多,会不好维护。
抽象工厂
把有关联关系的、属于一个产品系列的所有产品的接口函数,放在一个抽象工厂里面,派生类(具体产品的工厂)负责创建系列里面的产品。
//产品1 汽车
...
//产品2 车灯
class Light {
public:
virtual void Show() = 0;
};
class BMWLight : public Light
{
public:
void Show() { cout << "BMW light!" << endl; }
};
class AUDILight : public Light
{
public:
void Show() { cout << "AUDI light!" << endl; }
};
//抽象工厂
class AbstractFactory
{
public:
virtual Car* createCar(string name) = 0; // 工厂方法 创建汽车
virtual Light* createCarLight() = 0; // 工厂方法 创建汽车关联的产品,车灯
};
// 宝马工厂
class BMWFac : public AbstractFactory
{
public:
Car* createCar(string name)
{
return new BMW(name);
}
Light* createCarLight()
{
return new BMWLight();
}
};
// 奥迪工厂
class AUDIFac : public AbstractFactory
{
public:
Car* createCar(string name)
{
return new AUDI(name);
}
Light* createCarLight()
{
return new AUDILight();
}
};
int main() {
unique_ptr<AbstractFactory> bmwfactory(new BMWFac());
unique_ptr<AbstractFactory> audifactory(new AUDIFac());
unique_ptr<Car> car1(bmwfactory->createCar("x6"));
unique_ptr<Car> car2(audifactory->createCar("a8"));
unique_ptr<Light> light1(bmwfactory->createCarLight());
unique_ptr<Light> light2(audifactory->createCarLight());
car1->Show();
light1->Show();
car2->Show();
light2->Show();
return 0;
}
观察者模式
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
#include <list>
#include <iostream>
//设备接口类
class IDisplay {
public:
virtual void Show(double temperature) = 0;
virtual ~IDisplay() {}
};
//具体的设备类
class DisplayA : public IDisplay {
public:
void Show(double temperature) override {
std::cout << "DisplayA Show:" << temperature << std::endl;
}
};
class DisplayB : public IDisplay {
public:
void Show(double temperature) override {
std::cout << "DisplayB Show:" << temperature << std::endl;
}
};
//数据中心类,天气变化时通知所有设备
class DataCenter {
public:
void Attach(IDisplay* ob) { //添加设备
v.push_back(ob);
}
void Detach(IDisplay* ob) { //删除设备
v.remove(ob);
}
void Notify(double temper = 0.0) {
for (auto ob : v)
ob->Show(temper);
}
private:
std::list<IDisplay*> v;
};
int main() {
IDisplay* A = new DisplayA();
IDisplay* B = new DisplayB();
DataCenter* center = new DataCenter();
center->Attach(A);
center->Attach(B);
center->Notify(37.5);
center->Detach(B);
center->Notify(0.5);
return 0;
}
策略模式
定义一系列的算法,把他们一个一个封装起来,并且使他们可以互相替换。该模式使得算法可以独立于使用它的客户程序而变化。
如:新增算法、算法内容发生改变、切换算法
//打折方法接口类
class ProStategy {
public:
virtual double func(double x) = 0;
virtual ~ProStategy() {}
};
//具体的打折方法类
class Spring : public ProStategy {
public:
virtual double func(double x) override {
return x * 0.8;
}
};
class GuoQing : public ProStategy {
public:
virtual double func(double x) override {
return x * 0.9;
}
};
//商城类
class Market {
public:
Market(ProStategy* sss = nullptr) : s(sss) {}
~Market() {}
void Choose(ProStategy* sss) { //更换打折策略
if (sss != nullptr)
s = sss;
}
double Sell(double& x) { //计算售价
if (s != nullptr)
return s->func(x);
return 0.0;
}
private:
ProStategy* s;
};
int main() {
double x = 100.0;
ProStategy* s = new Spring(); //春节打折
ProStategy* g = new GuoQing();//国庆打折
Market* m = new Market(s);
std::cout << m->Sell(x) << std::endl;
m->Choose(g);
std::cout << m->Sell(x) << std::endl;
return 0;
}
单例模式
一个类在实例化时只能new出一个唯一的对象。
分类
- 懒汉式:系统运行时,实例并不存在,只有当需要使用该实例时,才回去创建并使用实例。要考虑线程安全。
- 饿汉式:系统一运行就初始化实例,当需要时直接调用即可。这种方式本身就线程安全。
特点
- 构造函数和析构函数为私有类型,目的是禁止外部构造和析构。
- 拷贝构造函数和赋值构造函数是私有类型,目的是禁止外部拷贝和赋值,确保实例的唯一性。
- 类中有一个获取实例的静态方法,可以全局访问。
懒汉模式
系统运行时,实例并不存在,只有当需要使用该实例时,才会去创建并使用实例。要考虑线程安全。
class single{
public:
static single* getInstance(){
if(instance == nullptr){
instance = new single();
}
return instance;
}
private:
static single* instance;
single(){};
};
single* single::instance = nullptr; //类外初始化静态变量
int main(){
single* s = single::getInstance();
}
class single{
public:
static single* getInstance()
{
if(instance == nullptr){
m.lock();
//再判断一次,确保不会再加锁期间多个线程同时进入
if(instance == nullptr){
instance = new single();
}
m.unlock();
}
return instance;
}
private:
static single* instance;
static std::mutex m;
single(){};
};
single* single::instance = nullptr;
mutex single::m;
饿汉模式
系统一运行就初始化实例,当需要时直接调用即可。这种方式本身就线程安全。
class single{
public:
static single* getInstance(){
return instance;
}
private:
static single* instance;
single(){};
};
//再main函数执行前就初始化instance对象,是线程安全的
singel* single::instance = new single; //类外初始化静态变量