目录

​一,设计模式​

​二,23种设计模式的分类​

​三,创建型模式​

​1,工厂方法模式√​

​(1)简单工厂模式​

​(2)工厂方法模式​

​2,抽象工厂模式√​

​(1)可聚合形式​

​(2)不可聚合形式​

​3,建造者模式​

​4,原型模式​

​5,单例模式√​

​饿汉式​

​懒汉式​

​懒汉式多线程​

​四,结构型模式​

​1,适配器模式​

​2,桥接模式​

​3,组合模式​

​4,装饰模式​

​5,外观模式​

​6,享元模式​

​7,代理模式​

​五,行为型模式​

​1,解释器模式​

​2,模板方法模式√​

​3,职责链模式​

​4,命令模式​

​5,迭代器模式​

​6,中介者模式​

​7,备忘录模式​

​8,观察者模式​

​9,状态模式​

​10,策略模式​

​11,访问者模式​


一,设计模式

设计模式(Design Pattern)是一套被反复使用的、多数人知晓的、经过分类编目的代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解。

二,23种设计模式的分类

根据其目的可分为创建型、结构型和行为型三种设计模式。


  • 创建型模式主要用于创建对象。  
  • 结构型模式主要用于处理类或对象的组合。  
  • 行为型模式主要用于描述对类或对象怎样交互和怎样分配职责。

根据范围,即模式主要是用于处理类之间关系还是处理对象之间的关系,可分为类模式和对象模式两种:


  • 类模式处理类和子类之间的关系,这些关系通过继承建立,在编译时刻就被确定下来,是属于静态的。
  • 对象模式处理对象间的关系,这些关系在运行时时刻变化,更具动态性。


范围\目的



创建型模式



结构型模式



行为型模式



类模式



工厂方法模式



(类)适配器模式



解释器模式

模板方法模式



对象模式



抽象工厂模式

建造者模式

原型模式

单例模式



(对象)适配器模式

桥接模式

组合模式

装饰模式

外观模式

享元模式

代理模式



职责链模式

命令模式

迭代器模式

中介者模式

备忘录模式

观察者模式

状态模式

策略模式

访问者模式


三,创建型模式

1,工厂方法模式√

(1)简单工厂模式

简单工厂模式,不属于23种工厂模式。

C语言很难真正实现设计模式,以简单工厂模式为例,假设天神既可以创造猫,也可以创造狗:

#include <stdio.h>

typedef void(*OutFun)(void*);

typedef struct Cat
{
char *catName;
OutFun outFun;
}Cat;

typedef struct Dog
{
char *dogName;
OutFun outFun;
}Dog;

enum Animal
{
CAT,
DOG
};

void AnimalOutFun(void* p)
{
printf("I'm %s\n", (char *)*((char **)p));
}

void* GetAnimal(int type)
{
if (type == CAT)
{
Cat *cat = (Cat *)malloc(sizeof(Cat));
cat->catName = "cat1";
cat->outFun = AnimalOutFun;
return cat;
}
if (type == DOG)
{
Dog* dog = (Dog *)malloc(sizeof(Dog));
dog->dogName = "dog1";
dog->outFun = AnimalOutFun;
return dog;
}
return NULL;
}


int main()
{
Cat *cat = (Cat *)GetAnimal(CAT);
cat->outFun(cat);
Dog* dog = (Dog *)GetAnimal(DOG);
dog->outFun(dog);
return 0;
}

运行结果:

I'm cat1

I'm dog1

其中GetAnimal函数就是工厂方法。

正如这个代码一样,C语言实现设计模式会很复杂,而 cat->outFun(cat) 这种自己处理自己的代码更是满天飞。

用C++实现同样的功能,头文件:

class Animals
{
public:
virtual void OutFun() {};
};

class Cat :public Animals
{
public:
void OutFun();
};

class Dog :public Animals
{
public:
void OutFun();
};

class Factory
{
public:
static Animals* GetAnimal(int type);
};

cpp:

enum Animal
{
CAT,
DOG
};

void Cat::OutFun() {
cout << "I'm Cat\n";
}
void Dog::OutFun() {
cout << "I'm Dog\n";
}

Animals* Factory::GetAnimal(int type)
{
if (type == CAT)
{
Animals* res = new Cat();
return res;
}
if (type == DOG)
{
Animals* res = new Dog();
return res;
}
return NULL;
}

int main()
{
Animals *cat = Factory::GetAnimal(CAT);
cat->OutFun();
Animals* dog = Factory::GetAnimal(DOG);
dog->OutFun();
return 0;
}

简单工厂模式由抽象产品类(Animals)、具体产品类(Cat等)、工厂(GetAnimal)组成​,抽象产品类和工厂类可以合并。

合并后的头文件:

class Animals
{
public:
virtual void OutFun() {};
static Animals* GetAnimal(int type);
};

class Cat :public Animals
{
public:
void OutFun();
};

class Dog :public Animals
{
public:
void OutFun();
};

cpp:

enum Animal
{
CAT,
DOG
};

void Cat::OutFun() {
cout << "I'm Cat\n";
}
void Dog::OutFun() {
cout << "I'm Dog\n";
}

Animals* Animals::GetAnimal(int type)
{
if (type == CAT)
{
Animals* res = new Cat();
return res;
}
if (type == DOG)
{
Animals* res = new Dog();
return res;
}
return NULL;
}

int main()
{
Animals *cat = Animals::GetAnimal(CAT);
cat->OutFun();
Animals* dog = Animals::GetAnimal(DOG);
dog->OutFun();
return 0;
}

因为工厂方法通常可以是静态函数,所以简单工厂模式也叫静态工厂模式。

(2)工厂方法模式

简单工厂模式中,每次新增产品都需要修改工厂,不符合开闭原则。

工厂方法模式由抽象产品类(Animals)、具体产品类(Cat等)、抽象工厂(Factory)、具体工厂(CatFactory等)组成

头文件:

class Animals
{
public:
virtual void OutFun() =0;
};

class Cat :public Animals
{
public:
void OutFun();
};

class Dog :public Animals
{
public:
void OutFun();
};

class Factory
{
public:
virtual Animals* GetAnimal() =0;
};

class CatFactory :public Factory
{
public:
Animals* GetAnimal();
};

class DogFactory :public Factory
{
public:
Animals* GetAnimal();
};

cpp:

void Cat::OutFun() {
cout << "I'm Cat\n";
}
void Dog::OutFun() {
cout << "I'm Dog\n";
}

Animals* CatFactory::GetAnimal()
{
Animals* res = new Cat();
return res;
}
Animals* DogFactory::GetAnimal()
{
Animals* res = new Dog();
return res;
}

int main()
{
CatFactory fac1;
Animals *cat = fac1.GetAnimal();
cat->OutFun();
DogFactory fac2;
Animals* dog = fac2.GetAnimal();
dog->OutFun();
return 0;
}

工厂方法模式也叫虚拟构造器模式、多态工厂模式。

新增产品不需要修改工厂,只需要新增具体工厂,符合开闭原则。

但缺点很明显,类太多了。

2,抽象工厂模式√

有很多交叉分类场景,比如天神既可以创造猫,也可以创造狗,但是创造的都是成年动物,而小猫和小狗是阎王安排投胎去的,那阎王也需要自己的工厂。

大猫大狗构成一个产品簇,小猫小狗构成一个产品簇,产品簇的分类和产品的分类构成交叉分类。

根据2个分类系能否用聚合形式表示,分为2种情况:

(1)可聚合形式

如果可以单独的表示产品簇的信息,然后用聚合的形式表示具体产品,那么具体工厂数是产品簇的分类数 + 产品的分类数。

class Animals
{
public:
virtual void OutFun() {};
static Animals* GetAnimal(int type);
};

class Cat :public Animals
{
public:
void OutFun() {
cout << "cat\n";
}
};

class Dog :public Animals
{
public:
void OutFun() {
cout << "dog\n";
}
};

enum Animal
{
CAT,
DOG
};

Animals* Animals::GetAnimal(int type)
{
if (type == CAT)
{
Animals* res = new Cat();
return res;
}
if (type == DOG)
{
Animals* res = new Dog();
return res;
}
return NULL;
}

class Size
{
public:
virtual void OutFun() {};
static Size* GetSize(int type);
};

class Big :public Size
{
public:
void OutFun() {
cout << "I'm big ";
}
};

class Small :public Size
{
public:
void OutFun() {
cout << "I'm small ";
}
};

enum Size_
{
BIG,
SMALL
};

Size* Size::GetSize(int type)
{
if (type == BIG)
{
Size* res = new Big();
return res;
}
if (type == SMALL)
{
Size* res = new Small();
return res;
}
return NULL;
}

class FinalAnimal {
public:
FinalAnimal(int animalType, int sizeType) {
animal = Animals::GetAnimal(animalType);
size = Size::GetSize(sizeType);
}
void OutFun() {
size->OutFun();
animal->OutFun();
}
private:
Animals* animal;
Size* size;
};

int main()
{
FinalAnimal(CAT, BIG).OutFun();
FinalAnimal(DOG, SMALL).OutFun();
return 0;
}

输出:

23种设计模式_简单工厂模式

(2)不可聚合形式

如果不能单独的表示产品簇的信息,那么具体工厂数 = 产品簇的分类数 * 产品的分类数。

class Animals {
public:
virtual void OutFun() {};
static Animals* GetAnimal(int animalType, int sizeType);
};

class BigAnimals :public Animals
{
public:
virtual void OutFun() {};
static BigAnimals* GetAnimal(int type);
};

class BigCat :public BigAnimals
{
public:
void OutFun() {
cout << "I'm big cat\n";
}
};

class BigDog :public BigAnimals
{
public:
void OutFun() {
cout << "I'm big dog\n";
}
};

enum Animal
{
CAT,
DOG
};

BigAnimals* BigAnimals::GetAnimal(int type)
{
if (type == CAT)
{
BigAnimals* res = new BigCat();
return res;
}
if (type == DOG)
{
BigAnimals* res = new BigDog();
return res;
}
return NULL;
}

class SmallAnimals :public Animals
{
public:
virtual void OutFun() {};
static SmallAnimals* GetAnimal(int type);
};

class SmallCat :public SmallAnimals
{
public:
void OutFun() {
cout << "I'm small cat\n";
}
};

class SmallDog :public SmallAnimals
{
public:
void OutFun() {
cout << "I'm small dog\n";
}
};

SmallAnimals* SmallAnimals::GetAnimal(int type)
{
if (type == CAT)
{
SmallAnimals* res = new SmallCat();
return res;
}
if (type == DOG)
{
SmallAnimals* res = new SmallDog();
return res;
}
return NULL;
}

enum Size_
{
BIG,
SMALL
};

Animals* Animals::GetAnimal(int animalType, int sizeType) {
if (sizeType == BIG) return (Animals*)BigAnimals::GetAnimal(animalType);
if (sizeType == SMALL) return (Animals*)SmallAnimals::GetAnimal(animalType);
return NULL;
}

int main()
{
Animals::GetAnimal(CAT, BIG)->OutFun();
Animals::GetAnimal(DOG, SMALL)->OutFun();
return 0;
}

输出:

23种设计模式_简单工厂模式_02

如果要新增产品簇(老狗和老猫),那么只需要新增一个OldAnimals类,新增一个GetAnimal方法即可。

如果要新增产品(大马和小马),那么每个产品簇都需要修改。

3,建造者模式

4,原型模式

5,单例模式√

​javascript:void(0)​

四,结构型模式

1,适配器模式

(1)类适配器模式

(2)对象适配器模式

2,桥接模式

3,组合模式

4,装饰模式

5,外观模式

6,享元模式

7,代理模式

五,行为型模式

1,解释器模式

2,模板方法模式√

解释:

模板方法模式,就是父类规定了统一的流程,子类去实现流程每一步的细节。

场景一:

当我们教小孩穿衣服的时候,我们希望小孩知道,先穿上衣,再穿裤子,再穿鞋子,这个是固定的流程,和衣服的颜色无关,和裤子是运动裤还是牛仔裤也无关。

有了这个概念之后,再教孩子各种上衣怎么穿,各种裤子怎么穿,各种鞋子怎么穿,孩子的脑海中就会有知识图谱的概念了。

实现:

我们用父类规定穿衣服的流程,子类去实现各个步骤如何操作。

#include<iostream>
using namespace std;

class dress
{
virtual void dressCoat()=0;
virtual void dressPants()=0;
virtual void dressShoes()=0;
public:
void dressAll()
{
dressCoat();
dressPants();
dressShoes();
cout<<endl;
}
};

class dressRed:public dress
{
void dressCoat(){
cout<<"Red coat ";
}
void dressPants(){
cout<<"Red pants ";
}
void dressShoes(){
cout<<"Red shoes ";
}
};

class dressBlue:public dress
{
void dressCoat(){
cout<<"Blue coat ";
}
void dressPants(){
cout<<"Blue pants ";
}
void dressShoes(){
cout<<"Blue shoes ";
}
};

int main()
{
dressRed d;
d.dressAll();
dressBlue d2;
d2.dressAll();
return 0;
}

输出:

Red coat Red pants Red shoes

Blue coat Blue pants Blue shoes

C语言模拟:

C语言没有这种代码机制,可以用函数指针实现回调机制,实现类似的效果。

参考我的毕设作品:​​本科毕业设计​

场景二:

如果各个子类的流程不完全相同,比如其中有一步有的子类不需要实现,那么我们可以把父类函数设为虚函数,提供一个空实现即可。

#include<iostream>
using namespace std;

class dress
{
virtual void dressCoat() {};
virtual void dressPants() {};
virtual void dressShoes() {};
public:
void dressAll()
{
dressCoat();
dressPants();
dressShoes();
cout << endl;
}
};

class dressRed :public dress
{
void dressCoat() {
cout << "Red coat ";
}
void dressPants() {
cout << "Red pants ";
}
void dressShoes() {
cout << "Red shoes ";
}
};

class dressBlue :public dress
{
void dressCoat() {
cout << "Blue coat ";
}
void dressPants() {
cout << "Blue pants ";
}
};

int main()
{
dressRed d;
d.dressAll();
dressBlue d2;
d2.dressAll();
return 0;
}

输出:

Red coat Red pants Red shoes

Blue coat Blue pants

3,职责链模式

4,命令模式

5,迭代器模式

6,中介者模式

7,备忘录模式

8,观察者模式

9,状态模式

10,策略模式

11,访问者模式