历史归档 · 开发与软件

设计模式笔记

单例、工厂、观察者等常见设计模式的学习记录与实现要点。

5 分钟阅读
  1. 单例模式

在系统中,一个类只有唯一的一个实例,并且该实例可以全局访问。

可以用于管理资源;如日志,线程池。

设计思路:

  • 只能有一个实例意味着不能在类的外部创造实例,那么其默认构造函数必须是private。此外拷贝构造函数和复制函数可以是private,可以delete掉。
  • 需要提供全局的访问点,所以得有个函数是static,并且返回一个static实例的引用。
class Singleton {
public:
Singleton(Singleton const& input) = delete;
Singleton& operator = (Singleton const& input) = delete;

static Singleton& getInstance()
{
static Singleton singleton;
return(singleton);
}

void fun()
{
cout << "do something" << endl;
}

private:
Singleton() = default;
};

int main()
{
Singleton& temp = Singleton::getInstance();
temp.fun();
return(0);
}

  1. 工厂模式

工厂模式的主要作用有:

  • 封装对象的创建
  • 分离对象封装和操作的过程
  • 用于批量管理对象的创建过程,便于程序的维护和扩展。

主要包括三种类型:

  1. 简单工厂模式
  2. 工厂方法模式(正宗)
  3. 抽象工厂模式

1. 简单工厂模式

这个模式是工厂模式最简单的一种实现。对于不同产品的创建定义一个工厂类,将产品类型作为参数传入到工厂的创建函数,根据类型分支选择不同的产品构造函数。

简单工厂模式只是一个对创建过程的封装。

为什么叫“简单”——不同的产品由同一个工厂制造

typedef enum productTypeTag
{
typeA, typeB, typeC
}PRODUCTTYPE;

class product  //base class
{
public:
virtual void who() = 0;
virtual ~product()
{
cout << "product BASE destructor" << endl;
};
};

class productA :public product
{
public:
void who() override
{
cout << "I am A" << endl;
}

virtual ~productA()
{
cout << "product A destructor" << endl;
};
};

class productB :public product
{
public:
void who() override
{
cout << "I am B" << endl;
}
virtual ~productB()
{
cout << "product B destructor" << endl;
};
};

class productC :public product
{
public:
void who() override
{
cout << "I am C" << endl;
}
virtual ~productC()
{
cout << "product C destructor" << endl;
};
};

class factory
{
public:
product* createProduct(PRODUCTTYPE type)
{
switch (type)
{
case typeA:
return(new productA());
case typeB:
return(new productB());
case typeC:
return(new productC());
default:
return(NULL);
}
}
};

int main()
{
factory creator;
product* A = creator.createProduct(typeA);
product* B = creator.createProduct(typeB);
product* C = creator.createProduct(typeC);

A->who();
B->who();
C->who();

if (A)
{
delete A;
A = nullptr;
}
if (B)
{
delete B;
B = nullptr;
}
if (C)
{
delete C;
C = nullptr;
}

return(0);
}

2. 工厂方法模式

工厂方法模式在简单工程模式的基础上增加了对工程的基类抽象:

  • 不同的产品由不同的工厂的生产(这些工程是抽象工程基类派生而出)

对于简单工厂模式的有点:

  • 便于后期增加或删除产品的种类
class product  //base class
{
public:
virtual void who() = 0;
virtual ~product()
{
cout << "product BASE destructor" << endl;
};
};

class productA :public product
{
public:
void who() override
{
cout << "I am A" << endl;
}

virtual ~productA()
{
cout << "product A destructor" << endl;
};
};

class productB :public product
{
public:
void who() override
{
cout << "I am B" << endl;
}
virtual ~productB()
{
cout << "product B destructor" << endl;
};
};

class productC :public product
{
public:
void who() override
{
cout << "I am C" << endl;
}
virtual ~productC()
{
cout << "product C destructor" << endl;
};
};

class factory
{
public:
virtual product* createProduct() = 0;
};

class factoryA :public factory
{
public:
product* createProduct()
{
return(new productA());
}
};

class factoryB :public factory
{
public:
product* createProduct()
{
return(new productB());
}
};

class factoryC :public factory
{
public:
product* createProduct()
{
return(new productC());
}
};

int main()
{
factory* creatorA = new factoryA();
product* A = creatorA->createProduct();

factory* creatorB = new factoryB();
product* B = creatorB->createProduct();

factory* creatorC = new factoryC();
product* C = creatorC->createProduct();

A->who();
B->who();
C->who();

if (creatorA)
{
delete creatorA;
creatorA = nullptr;
}
if (creatorB)
{
delete creatorB;
creatorB = nullptr;
}
if (creatorC)
{
delete creatorC;
creatorC = nullptr;
}

if (A)
{
delete A;
A = nullptr;
}
if (B)
{
delete B;
B = nullptr;
}
if (C)
{
delete C;
C = nullptr;
}

return(0);
}

3. 抽象工厂模式

适用于结构多产品,而工厂方法模式适用于结构单一的产品。当具有多个抽象产品类型时,抽象工程便可以派上用场。

抽象工厂:

  • 低端工厂生产不同种类低端产品
  • 高端工厂生产不同种类高端产品
/* Product A */
class productA
{
public:
virtual void who() = 0;
};

class productALow :public productA
{
public:
void who() override
{
cout << "I am A low" << endl;
}
};

class productAHigh :public productA
{
public:
void who() override
{
cout << "I am A high" << endl;
}
};

/* Product B */
class productB
{
public:
virtual void who() = 0;
};

class productBLow :public productB
{
public:
void who() override
{
cout << "I am B low" << endl;
}
};

class productBHigh :public productB
{
public:
void who() override
{
cout << "I am B high" << endl;
}
};

/* Factory */
class factory
{
public:
virtual productA* producesorA() = 0;
virtual productB* producesorB() = 0;
};

class factoryLow :public factory
{
productA* producesorA() override
{
return(new productALow());
}

productB* producesorB() override
{
return(new productBLow());
}
};

class factoryHigh :public factory
{
productA* producesorA() override
{
return(new productAHigh());
}

productB* producesorB() override
{
return(new productBHigh());
}
};

int main()
{
factory* High = new factoryHigh();
productA* highA = High->producesorA();
productB* highB = High->producesorB();

factory* Low = new factoryLow();
productA* lowA = Low->producesorA();
productB* lowB = Low->producesorB();

highA->who();
highB->who();
lowA->who();
lowB->who();

delete High, highA, highB, Low, lowA, lowB;
High = nullptr;
highA = nullptr;
highB = nullptr;
Low = nullptr;
lowA = nullptr;
lowB = nullptr;
}

  1. 策略模式

这个模式定义并封装了一系列算法,这些算法可以相互替换。这让算法独立于使用它的客户程序,可以独立变化。

三种类型的 class:

  • 抽象策略类(基类)
  • 封装了相关算法和行为(派生类)
  • 持有一个策略类引用,以给客户端调用

下面举例来看看策略模式是怎样设计的。关于这例子的出处和应用场景,请点这里

class wind
{
public:
virtual void windType() = 0;
virtual ~wind() = default;
};

class windWarm :public wind
{
public:
void windType() override
{
cout << "The warm mode is on" << endl;
}
};

class windCold :public wind
{
public:
void windType() override
{
cout << "The cold mode is on" << endl;
}
};

class windStop :public wind
{
public:
void windType() override
{
cout << "The stop mode is on" << endl;
}
};

class windMode
{
public:
windMode(wind* input) :curWind(input) {};

void windType()
{
curWind->windType();
}

~windMode()
{
delete curWind;
}

private:
wind* curWind;
};

int main()
{
windMode* warm = new windMode(new windWarm());
windMode* cold = new windMode(new windCold());
windMode* stop = new windMode(new windStop());

warm->windType();
cold->windType();
stop->windType();

delete warm, cold, stop;
warm = nullptr;
cold = nullptr;
stop = nullptr;
}