这个文章的目的
我很早就知道有一个可以学设计模式的网站
一个乌克兰老哥搞得学设计模式的网站,还有爱好者直接翻译成中文的页面~
我一直没能有机会学一学~
每一种设计模式都有一个很生动的图解,还有对应的代码实现,其中也有C++等等常见的面向对象语言的实现
例如:
我学这些设计模式(C++实现)的时候,我在想一件很有意思的事情
如果用C语言来写会怎么样呢?
因为C++和C语言还是有些共同之处的吧
如果同样的设计模式,能不能用C语言来解读,或者说能不能用C语言来实现呢
于是乎,我就来尝试用C语言(编译环境基于VS 2022)模拟出它提供的例程中C++的那种行为来,于是乎有了这个文章
分成上下两P
下P
工厂方法
工厂方法的介绍: https://refactoringguru.cn/design-patterns/factory-method
工厂方法的C++实现: https://refactoringguru.cn/design-patterns/factory-method/cpp/example
我的理解就是
不同的"工厂"生产不同的"产品"
不同的“产品”可以做不同的"事"
不同的"工厂"都有一个统一的基类(我叫它抽象工厂类),它都能生产"产品"
不同的"产品"都有一个统一的基类(我叫它抽象产品类),它都能做"事"
如果用一个图(直白的图,不是UML图)来说,大概就是这样
通过这张图
可以知道产品和工厂都存在一个抽象到具体的过程~
在C++里面,这个天然就可以通过子父类的继承来实现,这没啥好说的~
任何产品和任何工厂都有各自统一的行为,产品可以做某种事情,工厂可以生产某种产品,做事和生产是一个抽象的接口
在C++里面,这个是通过子类去实现或者说重写了父类的方法来实现的。
那么重点来了,当切换成C语言
继承,我的理解可以通过"结构体层层套娃"来实现
方法重写,我的理解可以通过"函数指针"来实现
下面就是我模仿网站上C++实现,转换成C语言实现的工厂方法
#include <stdio.h>
#include <string.h>
#include <iostream>
/// <summary>
/// 抽象产品
/// </summary>
typedef struct
{
//产品的具体操作函数指针
void (*Operation)(void);
}Product;
/// <summary>
/// 具体产品1
/// </summary>
typedef struct
{
//继承自抽象产品
Product base;
}ConcreteProduct1;
/// <summary>
/// 具体产品2
/// </summary>
typedef struct
{
//继承自抽象产品
Product base;
}ConcreteProduct2;
/// <summary>
/// 具体产品1的操作
/// </summary>
/// <param name=""></param>
void Product1Operation(void)
{
std::cout << "你好,产品1" << std::endl;
}
/// <summary>
/// 具体产品2的操作
/// </summary>
/// <param name=""></param>
void Product2Operation(void)
{
std::cout << "你好,产品2" << std::endl;
}
/// <summary>
/// 抽象工厂
/// </summary>
typedef struct
{
/// <summary>
/// 生产产品的工厂方法指针
/// </summary>
Product* (*FactoryMethod)();
}Creator;
/// <summary>
/// 具体工厂1
/// </summary>
typedef struct
{
/// <summary>
/// 继承自抽象工厂
/// </summary>
Creator base;
}ConcreteCreator1;
/// <summary>
/// 具体工厂2
/// </summary>
typedef struct
{
/// <summary>
/// 继承自抽象工厂
/// </summary>
Creator base;
}ConcreteCreator2;
/// <summary>
/// 工厂方法1,返回生产出的产品1
/// </summary>
/// <returns></returns>
Product* FactoryMethod1()
{
//生产具体产品1
ConcreteProduct1* ptr = (ConcreteProduct1*)malloc(sizeof(ConcreteProduct1));
if (ptr != NULL)
{
//绑定具体产品1的操作
ptr->base.Operation = Product1Operation;
}
//返回抽象产品指针
return (Product*)ptr;
}
/// <summary>
/// 工厂方法2,返回生产出的产品2
/// </summary>
/// <returns></returns>
Product* FactoryMethod2()
{
//生产具体产品2
ConcreteProduct2* ptr = (ConcreteProduct2*)malloc(sizeof(ConcreteProduct2));
if (ptr != NULL)
{
//绑定具体产品2的操作
ptr->base.Operation = Product2Operation;
}
//返回抽象产品指针
return (Product*)ptr;
}
void SomeOperation(Creator* _this)
{
//具体工厂尝试生产出对应的抽象产品
Product* product = _this->FactoryMethod();
std::cout << "工厂生产出: ";
//抽象产品做具体的动作
product->Operation();
free(product);
}
/// <summary>
/// 客户端
/// </summary>
/// <param name="creator"></param>
void ClientCode(Creator* creator)
{
std::cout << "我是使用者,我不管具体使用的是啥: \n";
SomeOperation(creator);
}
void C_FactoryMethod(void)
{
std::cout << "C语言版本的工厂方法" << std::endl;
std::cout << "工厂1启动\n";
ConcreteCreator1 creator1;
creator1.base.FactoryMethod = FactoryMethod1;
ClientCode(&creator1.base);
std::cout << "工厂2启动\n";
ConcreteCreator2 creator2;
creator2.base.FactoryMethod = FactoryMethod2;
ClientCode(&creator2.base);
}
运行的效果
在C语言环境下,我通过结构体的套娃实现了继承的效果,函数指针模拟了方法重写的效果出来
抽象产品,包含抽象产品做事的函数指针
具体产品,在结构体定义的时候包含抽象产品的结构体,这样就有了做事的函数指针了,那么后面初始化具体产品的时候就需要把具体产品需要做的事(也就是函数指针指向的函数)绑定上去就可以了。同理具体工厂的弄法也是类似的。
在客户使用的时候,就可以通过父结构体来处理不同的工厂,生产的不同的产品,产品再做不同的事情,而不需要去直接访问具体的产品的结构体中的方法。
只是说,在C语言的环境下,它的结构体不能包含函数,但是可以包含函数指针,这样也算是间接的包含了函数.
就像它网页上说的那样
- 创建者和具体产品直接没有很紧密的联系
- 后续加入新的创建者,新的产品只需要按照这个模式添加就可以,不需要改原来的代码
抽象工厂方法
抽象工厂方法的介绍: https://refactoringguru.cn/design-patterns/abstract-factory
抽象工厂方法的C++实现: https://refactoringguru.cn/design-patterns/abstract-factory/cpp/example
这个给我的感觉就是工厂方法的升级版本~
类似于工厂方法,但是这个更进一步,更细了
可以生产更多的"产品",“产品”可以做的"事"更多
但是套路还是和工厂方法类似
我的理解就是
不同的"工厂"生产不同的"产品"
不同的“产品”可以做不同的"事"
不同的"工厂"都有一个统一的基类(我叫它抽象工厂类),它都能生产"产品"
不同的"产品"都有一个统一的基类(我叫它抽象产品类),它都能做"事"
如果用一个图(直白的图,不是UML图)来说,大概就是这样
抽象工厂可以生产两种抽象产品,分别事抽象产品A和B
抽象产品A只能干一种事
抽象产品B可以干两种事,分别是事情1和事情2.
然后抽象工厂,通过继承得到了两个不同的工厂
然后抽象产品,通过继承得到了4种产品~
也是类似的,客户不需要直接解除具体的工厂和产品,它只需要知道工厂可以生产产品,产品可以干活就可以了,具体的无需知晓。
代码实现,也是函数指针+结构体套娃的方式
#include <stdio.h>
#include <string.h>
#include <iostream>
/// <summary>
/// 抽象产品A
/// </summary>
typedef struct
{
/// <summary>
/// 抽象产品A干活
/// </summary>
/// <returns></returns>
void (*UsefullFunctionA)(void);
}AbstractProductA;
/// <summary>
/// 具体产品A1
/// </summary>
typedef struct
{
//继承自抽象产品A
AbstractProductA base;
}ConcreteProductA1;
/// <summary>
/// 具体产品A1干活
/// </summary>
/// <param name=""></param>
void UsefullFunctionA1Operation(void)
{
std::cout << "具体产品A1干活.\r\n";
}
/// <summary>
/// 具体产品A2
/// </summary>
typedef struct
{
//继承自抽象产品A
AbstractProductA base;
}ConcreteProductA2;
/// <summary>
/// 具体产品A2干活
/// </summary>
/// <param name=""></param>
void UsefullFunctionA2Operation(void)
{
std::cout << "具体产品A2干活.\r\n";
}
/// <summary>
/// 抽象产品B
/// </summary>
typedef struct
{
/// <summary>
/// 抽象产品B干活1
/// </summary>
/// <returns></returns>
void (*UsefullFunctionB)(void);
/// <summary>
/// 抽象产品B干活2
/// </summary>
/// <returns></returns>
void (*AnotherUsefulFunctionB)(AbstractProductA * collaborator);
}AbstractProductB;
/// <summary>
/// 具体产品B1
/// </summary>
typedef struct
{
/// <summary>
/// 继承自抽象产品B
/// </summary>
AbstractProductB base;
}ConcreteProductB1;
/// <summary>
/// 具体产品B2
/// </summary>
typedef struct
{
/// <summary>
/// 继承自抽象产品B
/// </summary>
AbstractProductB base;
}ConcreteProductB2;
/// <summary>
/// 具体产品B1干活1
/// </summary>
/// <param name=""></param>
void UsefullFunctionB1Operation(void)
{
std::cout << "具体产品B1干活1.\r\n";
}
/// <summary>
/// 具体产品B2干活1
/// </summary>
/// <param name=""></param>
void UsefullFunctionB2Operation(void)
{
std::cout << "具体产品B2干活1.\r\n";
}
/// <summary>
/// 具体产品B1干活2
/// </summary>
/// <param name="collaborator"></param>
void AnotherUsefulFunctionB1(AbstractProductA* collaborator)
{
std::cout << "具体产品B1干活2.\r\n";
std::cout << "顺带--->";
collaborator->UsefullFunctionA();
}
/// <summary>
/// 具体产品B2干活2
/// </summary>
/// <param name="collaborator"></param>
void AnotherUsefulFunctionB2(AbstractProductA* collaborator)
{
std::cout << "具体产品B2干活2.\r\n";
std::cout << "顺带--->";
collaborator->UsefullFunctionA();
}
/// <summary>
/// 抽象工厂
/// </summary>
typedef struct
{
/// <summary>
/// 生产抽象产品A
/// </summary>
/// <returns></returns>
AbstractProductA* (*CreateProductA)(void);
/// <summary>
/// 生产抽象产品B
/// </summary>
/// <returns></returns>
AbstractProductB* (*CreateProductB)(void);
}AbstracFactory;
// <summary>
/// 具体工厂1
/// </summary>
typedef struct
{
/// <summary>
/// 继承自抽象工厂
/// </summary>
AbstracFactory base;
}ConcreteFactory1;
/// <summary>
/// 生产具体产品A1
/// </summary>
/// <param name=""></param>
/// <returns></returns>
AbstractProductA* FactoryCreateProductA1(void)
{
ConcreteProductA1* p = (ConcreteProductA1*)malloc(sizeof(ConcreteProductA1));
if (p != NULL)
{
p->base.UsefullFunctionA = UsefullFunctionA1Operation;
}
return (AbstractProductA*)p;
}
/// <summary>
/// 生产具体产品B1
/// </summary>
/// <param name=""></param>
/// <returns></returns>
AbstractProductB* FactoryCreateProductB1(void)
{
ConcreteProductB1* p = (ConcreteProductB1*)malloc(sizeof(ConcreteProductB1));
if (p != NULL)
{
p->base.UsefullFunctionB = UsefullFunctionB1Operation;
p->base.AnotherUsefulFunctionB = AnotherUsefulFunctionB1;
}
return (AbstractProductB*)p;
}
// <summary>
/// 具体工厂2
/// </summary>
typedef struct
{
/// <summary>
/// 继承自抽象工厂
/// </summary>
AbstracFactory base;
}ConcreteFactory2;
/// <summary>
/// 生产具体产品A2
/// </summary>
/// <param name=""></param>
/// <returns></returns>
AbstractProductA* FactoryCreateProductA2(void)
{
ConcreteProductA2* p = (ConcreteProductA2*)malloc(sizeof(ConcreteProductA2));
if (p != NULL)
{
p->base.UsefullFunctionA = UsefullFunctionA2Operation;
}
return (AbstractProductA*)p;
}
/// <summary>
/// 生产具体产品B2
/// </summary>
/// <param name=""></param>
/// <returns></returns>
AbstractProductB* FactoryCreateProductB2(void)
{
ConcreteProductB2* p = (ConcreteProductB2*)malloc(sizeof(ConcreteProductB2));
if (p != NULL)
{
p->base.UsefullFunctionB = UsefullFunctionB2Operation;
p->base.AnotherUsefulFunctionB = AnotherUsefulFunctionB2;
}
return (AbstractProductB*)p;
}
/// <summary>
/// 客户端
/// </summary>
/// <param name="factory"></param>
void ClientCode( AbstracFactory* factory)
{
AbstractProductA* a = factory->CreateProductA();
AbstractProductB* b = factory->CreateProductB();
a->UsefullFunctionA();
b->UsefullFunctionB();
b->AnotherUsefulFunctionB(a);
free(a);
free(b);
}
void C_AbstractFactory(void)
{
std::cout << "C语言版本的抽象工厂方法" << std::endl;
std::cout << "我是使用者,我不管具体使用的是啥:\n";
std::cout << "具体工厂1:\n";
ConcreteFactory1 f1;
f1.base.CreateProductA = FactoryCreateProductA1;
f1.base.CreateProductB = FactoryCreateProductB1;
ClientCode(&f1.base);
std::cout << "具体工厂2:\n";
ConcreteFactory2 f2;
f2.base.CreateProductA = FactoryCreateProductA2;
f2.base.CreateProductB = FactoryCreateProductB2;
ClientCode(&f2.base);
}
运行的效果
生成器
生成器的介绍: https://refactoringguru.cn/design-patterns/builder
生成器的C++实现: https://refactoringguru.cn/design-patterns/builder/cpp/example
我对这个设计模式的理解:
某些复杂的对象,可能是由很多个小对象组成的,初始化这个复杂对象需要连带初始化许多的小对象
但是复杂的对象有时候,需要将某些功能增加或者删除以实现别的需求,但是连带的这些初始化接口可能就有些出现"有些用到,有些用不到"的情况,造成很大的浪费,代码也不简洁~
那么如果把复杂对象的构建初始化,拆散,分解成可以独立的接口,而不是原来一股脑的写一个大的接口来初始化,由一个另外的类(也叫主管)来管理组合需要用的小对象的初始化。
例如生成一个复杂的对象由ABC三个部件组成
现在由一个生成器来分别生成A,B,C三个部件
注意上面的生成器是一个抽象的概念,部件也是抽象的概念,这里也是需要通过继承得到具体的生成器和具体的部件的
然后由一个叫“主管”的类来统一管理,存在若干种生成的方法,输出不同的复杂对象~
通过阅读C++的实现,可以看到主要使用了继承,方法重写,this指针。
类似的,转换成C语言实现,通过结构体套娃,函数指针分别模拟继承和方法重写,但是this指针就麻烦些,需要通过传入自身类型的变量指针来实现。本质上C++的this指针其实底下也是这个东西,只是帮用户包装了下~
另外这里还存在一些指针类型的转换,因为C语言下没有继承,所以只能是通过结构体指针强制转换的方式将子类的指针强转为父类的指针,指针的转换是需要小心谨慎的
#include <stdio.h>
#include <string.h>
#include <iostream>
#define MAX_SIZE 10
/// <summary>
/// 输出产品
/// </summary>
typedef struct
{
uint8_t parts_[MAX_SIZE];
uint8_t CurIndex;
}Product1;
void ListsParts(Product1 *p)
{
for (int i = 0; i < p->CurIndex; i++)
{
printf("%c\t", p->parts_[i]);
}
printf("\r\n");
}
struct ConcreteBuilder1;
/// <summary>
/// 抽象生成器
/// </summary>
typedef struct
{
void(*ProducePartA)(struct ConcreteBuilder1* p);
void(*ProducePartB)(struct ConcreteBuilder1* p);
void(*ProducePartC)(struct ConcreteBuilder1* p);
}Builder;
/// <summary>
/// 具体生成器
/// </summary>
struct ConcreteBuilder1
{
Builder base;
Product1* product;
}_ConcreteBuilder1;
void ConcreteBuilder1Reset(struct ConcreteBuilder1* p);
/// <summary>
/// 获得产品
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
Product1* ConcreteBuilder1_GetProduct(struct ConcreteBuilder1* p)
{
Product1* result = p->product;
ConcreteBuilder1Reset(p);
return result;
}
/// <summary>
/// 释放生成的产品
/// </summary>
/// <param name="p"></param>
void ConcreteBuilderFree(struct ConcreteBuilder1* p)
{
free(p->product);
}
/// <summary>
/// 具体生成器初始化
/// </summary>
/// <param name="p"></param>
void ConcreteBuilder1Reset(struct ConcreteBuilder1* p)
{
Product1 * pp = (Product1*)malloc(sizeof(Product1));
if (pp != NULL)
{
p->product = pp;
memset(p->product->parts_, 0, MAX_SIZE);
p->product->CurIndex = 0;
}
}
/// <summary>
/// 具体生成部件A
/// </summary>
/// <param name="p"></param>
void ConcreteBuilder1_ProducePartA(struct ConcreteBuilder1* p)
{
if (p->product->CurIndex < MAX_SIZE)
{
p->product->parts_[p->product->CurIndex] = 'A';
p->product->CurIndex++;
}
}
/// <summary>
/// 具体生成部件B
/// </summary>
/// <param name="p"></param>
void ConcreteBuilder1_ProducePartB(struct ConcreteBuilder1* p)
{
if (p->product->CurIndex < MAX_SIZE)
{
p->product->parts_[p->product->CurIndex] = 'B';
p->product->CurIndex++;
}
}
/// <summary>
/// 具体生成部件C
/// </summary>
/// <param name="p"></param>
void ConcreteBuilder1_ProducePartC(struct ConcreteBuilder1* p)
{
if (p->product->CurIndex < MAX_SIZE)
{
p->product->parts_[p->product->CurIndex] = 'C';
p->product->CurIndex++;
}
}
/// <summary>
/// 主管
/// </summary>
typedef struct
{
Builder* builder;
}Director;
/// <summary>
/// 主管设置生成器
/// </summary>
/// <param name="d"></param>
/// <param name="p"></param>
void Director_SetBuilder(Director * d,Builder* p)
{
d->builder = p;
}
/// <summary>
/// 主管生成最小产品
/// </summary>
/// <param name="d"></param>
void Director_BuildMinimalViableProduct(Director* d)
{
d->builder->ProducePartA((ConcreteBuilder1*)d->builder);
d->builder->ProducePartB((ConcreteBuilder1*)d->builder);
d->builder->ProducePartC((ConcreteBuilder1*)d->builder);
}
/// <summary>
/// 主管生成完整产品
/// </summary>
/// <param name="d"></param>
void Director_BuildFullFeaturedProduct(Director* d)
{
d->builder->ProducePartB((ConcreteBuilder1*)d->builder);
d->builder->ProducePartC((ConcreteBuilder1*)d->builder);
d->builder->ProducePartA((ConcreteBuilder1*)d->builder);
d->builder->ProducePartB((ConcreteBuilder1*)d->builder);
d->builder->ProducePartC((ConcreteBuilder1*)d->builder);
}
void ClientCode(Director* d)
{
ConcreteBuilder1 builder;
ConcreteBuilder1Reset(&builder);
builder.base.ProducePartA = ConcreteBuilder1_ProducePartA;
builder.base.ProducePartB = ConcreteBuilder1_ProducePartB;
builder.base.ProducePartC = ConcreteBuilder1_ProducePartC;
Director_SetBuilder(d, (Builder *) & builder);
std::cout << "主管生产基础款产品" << std::endl;
Director_BuildMinimalViableProduct(d);
Product1* p = ConcreteBuilder1_GetProduct(&builder);
ListsParts(p);
ConcreteBuilderFree(&builder);
std::cout << "主管生产完整款产品" << std::endl;
ConcreteBuilder1Reset(&builder);
Director_BuildFullFeaturedProduct(d);
p = ConcreteBuilder1_GetProduct(&builder);
ListsParts(p);
ConcreteBuilderFree(&builder);
std::cout << "主管生产DIY款产品" << std::endl;
ConcreteBuilder1Reset(&builder);
d->builder->ProducePartB((ConcreteBuilder1*)d->builder);
d->builder->ProducePartC((ConcreteBuilder1*)d->builder);
p = ConcreteBuilder1_GetProduct(&builder);
ListsParts(p);
ConcreteBuilderFree(&builder);
}
void Builder_C(void)
{
Director d;
ClientCode(&d);
}
运行的效果如下:
这种设计模式主要是解决生成组成类似,但是略有差异的复杂对象时不需要写很多的初始化函数的设计模式~
关键点在于复杂的产品可以被拆解成一个个小的部件来生成
但是实现下来就会需要新增很多的类,代码会变得很复杂~
原型
原型的介绍: https://refactoringguru.cn/design-patterns/prototype
原型的C++实现: https://refactoringguru.cn/design-patterns/prototype/cpp/example
这种设计模式解决的问题是复制一个复杂的对象,但是很多情况下其实无法知道复杂对象内部的构造,直接复制是不行的,就算可以,代码就一定会强依赖要复制的对象的代码
为了实现复制,这种模式下,会把复制的过程放到子类(也就是克隆后)的对象上,以一个方法来克隆对象,在这个方法里面,将原始对象中的各种成员变量的值初始化好。
也是通过继承,方法重写,外加了拷贝构造来实现的。
如果用C语言模仿来做,这个拷贝构造的模拟好像不太弄~,只能是做一个传入对象指针的Clone的函数来弄
为了实现方法重写,给两个不同的实例,这里还需要用void *指针,针对两个不同对象的拷贝函数,内部通过强制转换转成各自类型的指针来实现拷贝。
不得不说,这里C++确是是帮用户做了很多看不见的操作
#include <stdio.h>
#include <string.h>
#include <iostream>
typedef enum
{
PROTOTYPE_1 = 0,
PROTOTYPE_2
}Type;
struct Prototype;
/// <summary>
/// 原型
/// </summary>
typedef struct Prototype
{
char prototype_name_[100];
float prototype_field_;
//如果要模拟出拷贝构造那个行为,有传一个This指针那样的操作
Prototype*(*Clone)(void *);
}Prototype_;
//设置原型的方法
void PrototypeMethod(Prototype* p, float prototype_field)
{
printf("类型%s:原来的值是%f\r\n", p->prototype_name_, p->prototype_field_);
p->prototype_field_ = prototype_field;
printf("类型%s:现在给我设置为%f\r\n", p->prototype_name_, p->prototype_field_);
}
//克隆体1
typedef struct
{
/// <summary>
/// 继承自原型
/// </summary>
Prototype base;
/// <summary>
/// 克隆体1独特的字段
/// </summary>
float concrete_prototype_field1_;
}ConcretePrototype1;
/// <summary>
/// 克隆出克隆体1
/// </summary>
/// <param name=""></param>
/// <returns></returns>
Prototype* ConcretePrototype1_Clone(void * ptr)
{
ConcretePrototype1* p = (ConcretePrototype1*)malloc(sizeof(ConcretePrototype1));
ConcretePrototype1* ori = (ConcretePrototype1*)ptr;
if (p!=NULL)
{
//模拟拷贝构造
memcpy(p, ori, sizeof(ConcretePrototype1));
/*p->concrete_prototype_field1_ = ori->concrete_prototype_field1_;
p->base.prototype_field_ = ori->base.prototype_field_;
sprintf_s(p->base.prototype_name_, 100, "%s", ori->base.prototype_name_);
p->base.Clone = ori->base.Clone;*/
return (Prototype*)p;
}
else
{
return NULL;
}
}
/// <summary>
/// 克隆体2
/// </summary>
typedef struct
{
//继承自希望克隆的对象
Prototype base;
float concrete_prototype_field2_;
}ConcretePrototype2;
/// <summary>
/// 克隆出克隆体2
/// </summary>
/// <param name=""></param>
/// <returns></returns>
Prototype* ConcretePrototype2_Clone(void * ptr)
{
ConcretePrototype2* p = (ConcretePrototype2*)malloc(sizeof(ConcretePrototype2));
ConcretePrototype2* ori = (ConcretePrototype2*)ptr;
if (p != NULL)
{
//模拟拷贝构造
//p->concrete_prototype_field2_ = ori->concrete_prototype_field2_;
//p->base.prototype_field_ = ori->base.prototype_field_;
//sprintf_s(p->base.prototype_name_, 100, "%s", ori->base.prototype_name_);
//p->base.Clone = ori->base.Clone;
memcpy(p, ori, sizeof(ConcretePrototype2));
return (Prototype*)p;
}
else
{
return NULL;
}
}
/// <summary>
/// 原型工厂
/// </summary>
typedef struct
{
/// <summary>
/// 存放既有的原型
/// </summary>
Prototype * map[3];
}PrototypeFactory;
/// <summary>
/// 根据类型进行克隆
/// </summary>
/// <param name="p"></param>
/// <param name="type"></param>
/// <returns></returns>
Prototype* CreatePrototype(PrototypeFactory* p, Type type)
{
//调用对应类型的clone函数,顺带传入了待拷贝的指针
return p->map[(int)type]->Clone(p->map[(int)type]);
}
void Prototype_C()
{
PrototypeFactory pf;
ConcretePrototype1* ptr1;
ConcretePrototype2* ptr2;
//创建既有的克隆体,并初始化
ptr1 = (ConcretePrototype1 *)malloc(sizeof(ConcretePrototype1));
if (ptr1 != NULL)
{
sprintf_s(ptr1->base.prototype_name_, 100, "%s", "PROTOTYPE1");
ptr1->base.prototype_field_ = 50.f;
ptr1->concrete_prototype_field1_ = 50.f;
pf.map[(int)PROTOTYPE_1] = &ptr1->base;
pf.map[(int)PROTOTYPE_1]->Clone = ConcretePrototype1_Clone;
}
ptr2 = (ConcretePrototype2*)malloc(sizeof(ConcretePrototype2));
if (ptr2 != NULL)
{
sprintf_s(ptr2->base.prototype_name_, 100, "%s", "PROTOTYPE2");
ptr2->concrete_prototype_field2_ = 60.f;
ptr2->base.prototype_field_ = 60.f;
pf.map[(int)PROTOTYPE_2] = &ptr2->base;
pf.map[(int)PROTOTYPE_2]->Clone = ConcretePrototype2_Clone;
}
std::cout << "复制出原型1,和原来原型工厂里面的PROTOTYPE_1的对象,不一样" <<std::endl;;
Prototype* prototype = CreatePrototype(&pf, Type::PROTOTYPE_1);
std::cout << "原来原型工厂里面的PROTOTYPE_1的对象地址是"<< &pf.map[(int)PROTOTYPE_1] << std::endl;;
std::cout << "克隆出来的PROTOTYPE_1的对象地址是" << prototype << std::endl;;
PrototypeMethod(prototype, 90);
std::cout << "释放掉克隆出的PROTOTYPE_1"<< std::endl;;
free(prototype);
std::cout << "复制出原型2,和原来原型工厂里面的PROTOTYPE_2的对象,不一样" << std::endl;;
prototype = CreatePrototype(&pf, Type::PROTOTYPE_2);
std::cout << "原来原型工厂里面的PROTOTYPE_2的对象地址是" << &pf.map[(int)PROTOTYPE_2] << std::endl;;
std::cout << "克隆出来的PROTOTYPE_2的对象地址是" << prototype << std::endl;;
PrototypeMethod(prototype, 10);
std::cout << "释放掉克隆出的PROTOTYPE_2" << std::endl;;
free(prototype);
}
就像它教程上说的那样,可以克隆出对象,无需与它们所属的具体类耦合(C语言这里好像不太行,因为这里没有拷贝构造,我这里用memcpy来代替一条条复制),可以方便的生成复杂的对象(C++那个确实是方便了很多)
运行的效果
单例
单例的介绍: https://refactoringguru.cn/design-patterns/singleton
单例的C++实现: https://refactoringguru.cn/design-patterns/singleton/cpp/example
这个设计模式,感觉就是换了一种方式在用全局变量
变量就是一个,仅有一个,它只能被初始化一次,不能被再次赋值~
它C++的实现是将拷贝构造函数,赋值的重载运算符全部定义为了delete(即不能被调用),如果写了编译会直接报错.就留了一个带参数的构造函数用来初始化~
它教程上提到了线程安全的问题~
这个就需要看使用场景了,如果是单线程的,那么这个倒是没啥问题,因为不会同时调用,先调用的肯定就先new了,后面调用的就获取的是既有已经new好的变量可
但是如果多线程环境下,这个会是问题,会重复new,所以多线程需要在获取该变量的地方加锁机制~
这个在C语言环境下,好像挺常见的,先弄一个没有锁机制的~
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <mutex>
typedef struct
{
char value_[100];
}_Singleton;
typedef struct
{
_Singleton it;
}Singleton;
static Singleton * obj;
void SingletonInit(Singleton* obj,const char * str)
{
memcpy(obj->it.value_, str, 100);
}
const char* GetValue()
{
return obj->it.value_;
}
Singleton* GetInstance(const char* str)
{
if (obj == NULL)
{
obj = (Singleton*)malloc(sizeof(Singleton));
if (obj != NULL)
{
SingletonInit(obj, str);
}
}
return obj;
}
void ThreadFooC()
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
Singleton* singleton = GetInstance("FOO");
printf("ThreadFooC: %s\r\n", GetValue());
}
void ThreadBarC()
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
Singleton* singleton = GetInstance("BAR");
printf("ThreadBarC: %s\r\n", GetValue());
}
void Singleton_C(void)
{
std::cout << "多线程环境下单例\n";
std::thread t1(ThreadFooC);
std::thread t2(ThreadBarC);
t1.join();
t2.join();
}
再来个有锁机制的
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <mutex>
typedef struct
{
char value_[100];
}_Singleton;
typedef struct
{
_Singleton it;
}Singleton;
static Singleton * obj;
std::mutex mutex_;
void SingletonInit(Singleton* obj,const char * str)
{
memcpy(obj->it.value_, str, 100);
}
const char* GetValue()
{
return obj->it.value_;
}
Singleton* GetInstance(const char* str)
{
std::lock_guard<std::mutex> lock(mutex_);
if (obj == NULL)
{
obj = (Singleton*)malloc(sizeof(Singleton));
if (obj != NULL)
{
SingletonInit(obj, str);
}
}
return obj;
}
void ThreadFooC()
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
Singleton* singleton = GetInstance("FOO");
printf("ThreadFooC: %s\r\n", GetValue());
}
void ThreadBarC()
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
Singleton* singleton = GetInstance("BAR");
printf("ThreadBarC: %s\r\n", GetValue());
}
void Singleton_C(void)
{
std::cout << "多线程环境下单例(加锁)\n";
std::thread t1(ThreadFooC);
std::thread t2(ThreadBarC);
t1.join();
t2.join();
}
这个弄法感觉在面向对象里有点反面教材,但是在面向过程的语言里是很常见的事~
适配器
适配器的介绍: https://refactoringguru.cn/design-patterns/adapter
适配器的C++实现: https://refactoringguru.cn/design-patterns/adapter/cpp/example
这个设计模式我感觉就是中间层的概念~
如果存在既有的接口,后面新增了新的接口但是有需要适配原来的接口的话,那么就可以采用这种方式
C++的实现用了继承和方法重写,然后用了一个待适配的变量的指针传入适配器类变量中,进行适配处理
C语言下就使用函数指针和结构体嵌套来做~
#include <stdio.h>
#include <string.h>
#include <iostream>
/// <summary>
/// 目标对象
/// </summary>
typedef struct
{
int (*Request)();
}Target;
int TargetRequest()
{
return 12345678;
}
/// <summary>
/// 适配对象
/// </summary>
typedef struct
{
int (*SpecificRequest)();
}Adaptee;
int AdapteeSpecificRequest()
{
return -12345678;
}
/// <summary>
/// 适配器
/// </summary>
typedef struct
{
Target* _target;
Adaptee* _adaptee;
}Adapter;
/// <summary>
/// 从目标对象转适配对象的转换函数
/// </summary>
/// <param name="adapter"></param>
/// <returns></returns>
int AdapterConvFromTarget(Adapter* adapter)
{
int tmp = adapter->_target->Request();
//转换
int res = -tmp;
return res;
}
/// <summary>
/// 从适配对象转目标对象的转换函数
/// </summary>
/// <param name="adapter"></param>
/// <returns></returns>
int AdapterConvFromAdaptee(Adapter* adapter)
{
int tmp = adapter->_adaptee->SpecificRequest();
//转换
int res = -tmp;
return res;
}
void C_Adapter(void)
{
std::cout << "客户端,我原来只能和目标接口工作\n";
Target target;
target.Request = TargetRequest;
Adaptee adaptee;
adaptee.SpecificRequest = AdapteeSpecificRequest;
Adapter adapter;
adapter._adaptee = &adaptee;
adapter._target = ⌖
std::cout << "目标对象,输出 "<< target.Request()<<std::endl;
std::cout << "适配对象,输出 " << adaptee.SpecificRequest() << std::endl;
std::cout << "客户端,但是我可以通过适配器转换一下:\n";
std::cout << "适配器,目标->适配 输出 " << AdapterConvFromTarget(&adapter) << std::endl;
std::cout << "适配器,适配->目标 输出 " << AdapterConvFromAdaptee(&adapter) << std::endl;
}
桥接模式
桥接模式的介绍: https://refactoringguru.cn/design-patterns/bridge
桥接的C++实现: https://refactoringguru.cn/design-patterns/bridge/cpp/example
这个设计模式是建立抽象和实现的桥梁。抽象类定义了抽象部分的接口,而实现类则实现了实现部分的具体功能。桥接接口则将抽象类和实现类连接起来,使它们可以协同工作,最终的目的就是让抽象部分和实现部分分离。
看完C++的实现,其实原理也是继承和方法重载,有一个“桥”类对接抽象和实现,这里用了this指针,而用户调用的都是抽象的部分,无需关注具体的实现
换成C语言,就是结构体嵌套,函数指针,结构体指针作为参数的函数指针,前面都出现过类似的操作
#include <stdio.h>
#include <string.h>
#include <iostream>
/// <summary>
/// 干活
/// </summary>
typedef struct
{
std::string(*OperationImplementation)();
}Implementation;
/// <summary>
/// 平台A-干活
/// </summary>
typedef struct
{
Implementation base;
}ConcreteImplementationA;
std::string OperationImplementationA()
{
return "这里是平台A的API在干活\r\n";
}
/// <summary>
/// 平台B-干活
/// </summary>
typedef struct
{
Implementation base;
}ConcreteImplementationB;
std::string OperationImplementationB()
{
return "这里是平台B的API在干活\r\n";
}
/// <summary>
/// 抽象
/// </summary>
struct Abstraction;
typedef struct Abstraction
{
Implementation* implementation_;
std::string(*Operation)(Abstraction*);
}Abstraction;
std::string OperationAbstraction(Abstraction* p)
{
return "抽象: 基类干活:" + p->implementation_->OperationImplementation();
}
/// <summary>
/// 扩展抽象
/// </summary>
typedef struct
{
Abstraction base;
}ExtendedAbstraction;
std::string OperationExAbstraction(Abstraction* p)
{
return "扩展抽象: 干活:" + p->implementation_->OperationImplementation();
}
void ClientCode(Abstraction* abs)
{
std::cout << abs->Operation(abs);
}
void Bridge_C()
{
ConcreteImplementationA A;
ConcreteImplementationB B;
Abstraction ab;
ExtendedAbstraction Xab;
A.base.OperationImplementation = OperationImplementationA;
B.base.OperationImplementation = OperationImplementationB;
ab.Operation = OperationAbstraction;
ab.implementation_ = &A.base;
Xab.base.Operation = OperationExAbstraction;
Xab.base.implementation_ = &B.base;
ClientCode(&ab);
ClientCode(&Xab.base);
}
运行结果如下:
组合模式
组合模式的介绍: https://refactoringguru.cn/design-patterns/composite
组合模式的C++实现: https://refactoringguru.cn/design-patterns/composite/cpp/example
简单说,这种设计模式应用于那种树状的结构,通过将所有的元素定义一个统一的父类的方式来管理,并引入一个容器来管理树状的结构。
用户层面仅仅操作各个不同元素统一的父类实现多态,屏蔽了不同元素之间的差异。
这个用C++来实现是比较方便的。换做C语言来实现较为复杂。需要用好void指针和函数指针,来模拟出继承和多态的效果。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <list>
struct Component_C;
typedef struct Component_C
{
Component_C* parent_;
void (*Add)(void* _this, Component_C* compoent);
void (*Remove)(void* _this, Component_C* compoent);
bool (*IsComposite)(Component_C* _this);
std::string(*Operation)(void *);
}Component_C;
typedef void (*AddFunc)(void* _this, Component_C* compoent);
typedef void (*RemoveFunc)(void* _this, Component_C* compoent);
typedef bool (*IsCompositeFunc)(Component_C* _this);
typedef std::string(*OperationFunc)(void*);
Component_C* GetParent(Component_C * _this)
{
return _this->parent_;
}
void SetParent(Component_C* _this,Component_C* parent)
{
_this->parent_ = parent;
}
/// <summary>
/// 叶节点
/// </summary>
typedef struct
{
Component_C base;
}Leaf_C;
std::string Leaf_Operation(void *p)
{
return "叶";
}
/// <summary>
/// 复杂组件
/// </summary>
typedef struct Composite_C
{
Component_C base;
std::list<Component_C*> children_;
}Composite_C;
void Composite_Add(void* _this, Component_C* compoent)
{
Composite_C* ptr = (Composite_C*)_this;
ptr->children_.push_back(compoent);
SetParent( &ptr->base, compoent);
}
void Composite_Remove(void* _this, Component_C* compoent)
{
Composite_C* ptr = (Composite_C*)_this;
ptr->children_.remove(compoent);
SetParent(ptr->base.parent_, nullptr);
}
bool Composite_IsComposite(Component_C* _this)
{
return true;
}
std::string Composite_Operation(void* p)
{
Composite_C* ptr = (Composite_C*)p;
std::string result;
for (const Component_C* c : ptr->children_)
{
if (c == ptr->children_.back())//判断最后一个元素
{
result += c->Operation((void *)c);
}
else
{
result += c->Operation((void*)c) + "+";
}
}
return "分支(" + result + ")";
}
void ClientCode(Component_C* Component_C)
{
std::cout << "结果: " << Component_C->Operation(Component_C)<<std::endl;
}
/// <summary>
/// 往一个Component_C中加入另一个Component_C
/// </summary>
/// <param name="component1"></param>
/// <param name="component2"></param>
void ClientCode2(Component_C* component1, Component_C* component2)
{
if (component1->IsComposite(component1))
{
component1->Add(component1,component2);
}
std::cout << "结果: " << component1->Operation(component1);
}
void Leaf_Init(Leaf_C* ptr, OperationFunc p)
{
ptr->base.Operation = p;
}
void Composite_Init(Composite_C* ptr,
AddFunc add,
RemoveFunc remove,
IsCompositeFunc is, OperationFunc op)
{
ptr->base.Add = add;
ptr->base.Remove = remove;
ptr->base.IsComposite = is;
ptr->base.Operation = op;
}
void Add_Func(Component_C * _this,Component_C * _added)
{
_this->Add(_this, _added);
}
std::string Operation_Func(Component_C* _this, void* _par)
{
return _this->Operation((void *)_par);
}
void Composite_CC()
{
Leaf_C simple;
simple.base.Operation = Leaf_Operation;
std::cout << "客户端: 我有一个简单组件:\n";
ClientCode(&simple.base);
Composite_C root;
Composite_C tree;
Composite_C branch1;
Composite_C branch2;
Leaf_C leaf_1;
Leaf_C leaf_2;
Leaf_C leaf_3;
Leaf_Init(&leaf_1, Leaf_Operation);
Leaf_Init(&leaf_2, Leaf_Operation);
Leaf_Init(&leaf_3, Leaf_Operation);
Composite_Init(&root, Composite_Add, Composite_Remove, Composite_IsComposite, Composite_Operation);
Composite_Init(&tree, Composite_Add, Composite_Remove, Composite_IsComposite, Composite_Operation);
Composite_Init(&branch1, Composite_Add, Composite_Remove, Composite_IsComposite, Composite_Operation);
Composite_Init(&branch2, Composite_Add, Composite_Remove, Composite_IsComposite, Composite_Operation);
//设置根节点
SetParent(&root.base, &root.base);
//分支1添加两个节点
std::cout << "分支1添加两个节点" << std::endl;
Add_Func(&branch1.base,&leaf_1.base);
Add_Func(&branch1.base,&leaf_2.base);
std::cout << Operation_Func(&branch1.base, &branch1) << std::endl;
//分支2添加1一个节点
std::cout << "分支2添加1一个节点" << std::endl;
Add_Func(&branch2.base, &leaf_2.base);
std::cout << Operation_Func(&branch2.base, &branch2)<< std::endl;
//树节点添加两个分支
std::cout << "树节点添加两个分支" << std::endl;
Add_Func(&tree.base,&branch1.base);
Add_Func(&tree.base,&branch2.base);
std::cout<< Operation_Func(&tree.base, &tree)<<std::endl;
//树节点添加一个叶节点
std::cout << "树节点添加一个叶节点" << std::endl;
ClientCode2(&tree.base,&simple.base);
}
运行的效果
装饰器模式
装饰器模式的介绍: https://refactoringguru.cn/design-patterns/decorator
装饰器模式的C++实现: https://refactoringguru.cn/design-patterns/decorator/cpp/example
简单说,就是
创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能
说简单点,其实就是继承+套娃~
理解了C++那套弄法,我们直接上C语言实现的代码
C语言实现这种结构型设计模式还是比较复杂的。。。
涉及到嵌套和void指针的灵活使用
#include <stdio.h>
#include <string.h>
#include <iostream>
typedef std::string(*OperationFunc)(void*);
//基础组件
typedef struct
{
OperationFunc op;
}Component;
//具体组件
typedef struct
{
Component base;
}ConcreteComponent;
std::string ConcreteComponent_Operation(void* p)
{
return "ConcreteComponent";
}
void ConcreteComponentInit(ConcreteComponent* _this, OperationFunc op)
{
_this->base.op = op;
}
//基础装饰类
typedef struct
{
Component base;
Component* component_;
}BaseDecorator;
std::string BaseDecorator_Operation(void *p)
{
Component* ptr = (Component*)p;
return ptr->op(ptr);
}
/// <summary>
/// 基础装饰器初始化
/// </summary>
/// <param name="_this">待初始化的基础装饰器指针</param>
/// <param name="component">原有基础组件的指针</param>
/// <param name="op">装饰器扩展出来的方法</param>
void BaseDecoratorInit(BaseDecorator *_this,Component* component
, OperationFunc op)
{
_this->component_ = component;
_this->base.op = op;
}
/**
* 具体装饰A类
*/
typedef struct
{
BaseDecorator base;
}ConcreteDecoratorA;
/// <summary>
/// 具体装饰器A的初始化
/// </summary>
/// <param name="_this">待初始化的具体装饰器A</param>
/// <param name="component">原有基础组件的指针</param>
/// <param name="op">装饰器扩展出来的方法</param>
void ConcreteDecoratorAInit(ConcreteDecoratorA *_this,
Component* component
, OperationFunc op)
{
_this->base.component_ = component;
_this->base.base.op = op;
}
std::string ConcreteDecoratorA_Operation(void* p)
{
ConcreteDecoratorA* ptr = (ConcreteDecoratorA*)p;
//调用包装的基础组件的方法,并传入包装的基础组件指针
return "ConcreteDecoratorA(" +
ptr->base.component_->op(ptr->base.component_) +
")";
}
/**
* 具体装饰B类
*/
typedef struct
{
BaseDecorator base;
}ConcreteDecoratorB;
/// <summary>
/// 具体装饰器B的初始化
/// </summary>
/// <param name="_this">待初始化的具体装饰器B</param>
/// <param name="component">原有基础组件的指针</param>
/// <param name="op">装饰器扩展出来的方法</param>
void ConcreteDecoratorBInit(ConcreteDecoratorB* _this,
Component* component,
OperationFunc op)
{
_this->base.component_ = component;
_this->base.base.op = op;
}
std::string ConcreteDecoratorB_Operation(void* p)
{
ConcreteDecoratorB* ptr = (ConcreteDecoratorB*)p;
//调用包装的基础组件的方法,并传入包装的基础组件指针
return "ConcreteDecoratorB(" +
ptr->base.component_->op(ptr->base.component_) +
")";
}
void ClientCode(Component* component,void *p) {
// ...
std::cout << "结果: " << component->op(p);
// ...
}
void Decorator_C()
{
std::cout << "客户端: 我有一个简单组件:\n";
ConcreteComponent _simple;
Component* simple = &_simple.base;
ConcreteComponentInit(&_simple, ConcreteComponent_Operation);
ClientCode(simple,nullptr);
std::cout << "\n\n";
ConcreteDecoratorA _decorator1;
ConcreteDecoratorAInit(&_decorator1,
simple,
ConcreteDecoratorA_Operation);
Component* decorator1 = &_decorator1.base.base;
ConcreteDecoratorB _decorator2;
ConcreteDecoratorBInit(&_decorator2,
decorator1 ,
ConcreteDecoratorB_Operation);
Component* decorator2 = &_decorator2.base.base;
ClientCode(decorator2,&_decorator2);
std::cout << "\n\n";
}
运行的结果
外观模式
外观模式的介绍: https://refactoringguru.cn/design-patterns/facade
外观模式的C++实现: https://refactoringguru.cn/design-patterns/facade/cpp/example
这个感觉和适配器有点像,类似于弄了一个中间层的感觉,就是方便操作复杂子系统所作了一个屏蔽层.
外观类就像给需要访问的复杂子系统包了一个外套一样,对外有限度的提供接口访问复杂子系统,减少耦合。
把C++的代码看懂,整个C语言的
#include <stdio.h>
#include <string.h>
#include <iostream>
typedef struct
{
std::string(*Operation1)();
std::string(*OperationN)();
}Subsystem1;
std::string Subsystem1_Operation1() {
return "模拟子系统1: 就绪!\n";
}
std::string Subsystem1_OperationN() {
return "模拟子系统1: 干活!\n";
}
typedef struct
{
std::string(*Operation1)();
std::string(*OperationZ)();
}Subsystem2;
std::string Subsystem2_Operation1() {
return "模拟子系统2: 就绪!\n";
}
std::string Subsystem2_OperationZ() {
return "模拟子系统2: 干活!\n";
}
struct Facade;
typedef std::string(*Facade_Func)(Facade* _this);
/// <summary>
/// 外观类
/// </summary>
typedef struct Facade
{
Subsystem1* subsystem1_;
Subsystem2* subsystem2_;
std::string(*Operation)(Facade*);
}Facade;
void Facade_Init(Facade* p, Facade_Func pFunc)
{
if (p->subsystem1_ == nullptr)
{
p->subsystem1_ = (Subsystem1*)malloc(sizeof(Subsystem1));
p->subsystem1_->Operation1 = Subsystem1_Operation1;
p->subsystem1_->OperationN = Subsystem1_OperationN;
}
if (p->subsystem2_ == nullptr)
{
p->subsystem2_ = (Subsystem2*)malloc(sizeof(Subsystem2));
p->subsystem2_->Operation1 = Subsystem2_Operation1;
p->subsystem2_->OperationZ = Subsystem2_OperationZ;
}
p->Operation = pFunc;
}
std::string Facade_Operation(Facade *_this) {
std::string result = "外观类初始化子系统\n";
result += _this->subsystem1_->Operation1();
result += _this->subsystem2_->Operation1();
result += "外观类让子系统干活\n";
result += _this->subsystem1_->OperationN();
result += _this->subsystem2_->OperationZ();
return result;
}
void Facade_Dele(Facade* p)
{
if (p->subsystem1_ != nullptr)
{
free(p->subsystem1_);
}
if (p->subsystem2_ != nullptr)
{
free(p->subsystem2_);
}
}
void ClientCode(Facade* facade) {
std::cout << facade->Operation(facade);
}
void Facade_C() {
Facade facade;
facade.subsystem1_ = nullptr;
facade.subsystem2_ = nullptr;
Facade_Init(&facade, Facade_Operation);
ClientCode(&facade);
Facade_Dele(&facade);
}
享元模式
享元模式的介绍: https://refactoringguru.cn/design-patterns/flyweight
享元模式的C++实现: https://refactoringguru.cn/design-patterns/flyweight/cpp/example
简单说,就是把大量类似的变量中的共性的部分取出来封装,然后独特的进行封装。共性的不重复创造,仅仅创造独特的部分。目的是节约内存。
这个C++的例子还写的挺复杂的吧,换成C来写,这个结构体中包含string,这种一定要用new来处理,不然一定会内存有问题。
动态内存一多起来,复杂起来,C++就有优势了
#include <iostream>
/// <summary>
/// 共享状态
/// </summary>
typedef struct
{
std::string brand_;
std::string model_;
std::string color_;
}SharedState;
void SharedState_Init(SharedState *p,
std::string brand,
std::string model,
std::string color
)
{
p->brand_ = brand;
p->model_ = model;
p->color_ = color;
}
std::string SharedState_ToString(SharedState*p)
{
return "[" + p->brand_ + " , " + p->model_ + " , " + p->color_ + " ]";
}
std::string GetKey(const SharedState* ss)
{
return ss->brand_ + "_" + ss->model_ + "_" + ss->color_;
}
/// <summary>
/// 独特的状态
/// </summary>
typedef struct
{
std::string owner_;
std::string plates_;
}UniqueState;
void UniqueState_Init(
UniqueState *p,
std::string owner,
std::string plates
)
{
p->owner_ = owner;
p->plates_ = plates;
}
std::string UniqueState_ToString(UniqueState* p)
{
return "[" + p->owner_ + " , " + p->plates_ + " ]";
}
typedef struct
{
SharedState* shared_state_;
}Flyweight;
void Flyweight_Init(Flyweight * p, SharedState* shared_state)
{
p->shared_state_ = shared_state;
}
SharedState* Flyweight_State(Flyweight* p)
{
return p->shared_state_;
}
std::string Flyweight_ToString(Flyweight* p, UniqueState*q)
{
if ((p->shared_state_ != nullptr)&&(q!=nullptr))
{
return "享元: 显示共享部分 (" + SharedState_ToString(p->shared_state_)+
") 和独特部分 (" + UniqueState_ToString(q) + ") 的状态.\n";
}
else
{
return "空\r\n";
}
}
typedef struct
{
std::string _key;
Flyweight _value;
}KeyValueMap;
#define MAX_SIZE 10u
//用数组代替unordered_map,简单的,没有删除功能,只能新增
typedef struct
{
KeyValueMap flyweights_[MAX_SIZE];
int _index;
}FlyweightFactory;
bool FlyweightFactory_Add(FlyweightFactory*p,
SharedState*s)
{
if (p->_index < MAX_SIZE)
{
p->flyweights_[p->_index]._key
= GetKey(s);
p->flyweights_[p->_index]._value.shared_state_ =s;;
SharedState_Init(p->flyweights_[p->_index]._value.shared_state_,
s->brand_,
s->model_,
s->color_);
p->_index++;
return true;
}
else
{
std::cout << "元素太多,添加失败\r\n";
return false;
}
}
Flyweight GetFlyweight(FlyweightFactory* p,
SharedState* s)
{
std::string key = GetKey(s);
for (size_t i = 0; i < p->_index; i++)
{
if (p->flyweights_[i]._key == key)
{
std::cout << "享元: 返回既有的.\n";
return p->flyweights_[i]._value;
}
}
std::cout << "享元: 找不到,创建新的\n";
SharedState* ss = new SharedState();//这里没有办法,因为用了String,这里必须用new才行,不能用malloc
ss->brand_ = s->brand_;
ss->color_ = s->color_;
ss->model_ = s->model_;
bool ret = FlyweightFactory_Add(p,ss);
if (ret == true)
{
return p->flyweights_[p->_index-1]._value;
}
else
{
std::cout << "享元: 满了,返回最后一个\n";
return p->flyweights_[p->_index-1]._value;
}
}
void ListFlyweights(FlyweightFactory* p)
{
std::cout << "\n享元: 我有 " << p->_index << "个享元:\n";
for (size_t i = 0; i < p->_index; i++)
{
std::cout<< SharedState_ToString(p->flyweights_[i]._value.shared_state_)<<std::endl;
}
}
void AddCarToPoliceDatabase
(
FlyweightFactory* ff,
const std::string plates,
const std::string owner,
const std::string brand,
const std::string model,
const std::string color)
{
std::cout << "\n客户端: 添加一辆车到数据库.\n";
SharedState t;
UniqueState u;
SharedState_Init(&t, brand, model, color);
UniqueState_Init(&u, owner, plates);
Flyweight flyweight = GetFlyweight(ff, &t);
std::cout<< Flyweight_ToString(&flyweight, &u)<<std::endl;
}
void Flyweight_C()
{
FlyweightFactory ff;
ff._index = 0;
for (size_t i = 0; i < MAX_SIZE; i++)
{
ff.flyweights_[i]._key = "";
ff.flyweights_[i]._value.shared_state_ = NULL;
}
SharedState tmp;
SharedState_Init(&tmp, "Chevrolet", "Camaro2018", "pink");
FlyweightFactory_Add(&ff, &tmp);
SharedState tmp1;
SharedState_Init(&tmp1, "Mercedes Benz", "C300", "black");
FlyweightFactory_Add(&ff, &tmp1);
SharedState tmp2;
SharedState_Init(&tmp2, "BMW", "M5", "red");
FlyweightFactory_Add(&ff, &tmp2);
SharedState tmp3;
SharedState_Init(&tmp3, "BMW", "X6", "white");
FlyweightFactory_Add(&ff, &tmp3);
ListFlyweights(&ff);
AddCarToPoliceDatabase(&ff,
"CL234IR",
"James Doe",
"BMW",
"M5",
"red");
AddCarToPoliceDatabase(&ff,
"CL234IR",
"James Doe",
"BMW",
"X1",
"red");
AddCarToPoliceDatabase(&ff,
"CL234IR",
"James Doe",
"BMW",
"M5",
"red");
AddCarToPoliceDatabase(&ff,
"CL234IR",
"James Doe",
"BMW",
"X7",
"black");
ListFlyweights(&ff);
}
代理模式
代理模式的介绍: https://refactoringguru.cn/design-patterns/proxy
代理模式的C++实现: https://refactoringguru.cn/design-patterns/proxy/cpp/example
这个模式我感觉有点像之前的适配器,也有点像装饰。简单说
就是在复杂的系统前面加了一个中间层,中间层可以实现很多东西,而不需要去改复杂系统
C++的看完了,C语言的自然也是可以写出来的
#include <stdio.h>
#include <string.h>
#include <iostream>
typedef struct
{
void (*Request)(void *);
}Subject;
typedef void (*RequestHandler)(void *);
void Subject_Request(void*p)
{
Subject* pp = (Subject*)p;
pp = pp;
std::cout << "Subject: Handling request.\n";
}
typedef struct
{
Subject base;
}RealSubject;
void RealSubject_Request(void* p)
{
RealSubject* pp = (RealSubject*)p;
pp = pp;
std::cout << "RealSubject: Handling request.\n";
}
void RealSubject_Init(RealSubject * r, RequestHandler f)
{
r->base.Request = f;
}
typedef struct
{
Subject base;
RealSubject* real_subject_;
}Proxy;
void LogAccess(Proxy* p)
{
std::cout << "Proxy: Logging the time of request.\n";
}
bool CheckAccess(Proxy* p)
{
std::cout << "Proxy: Checking access prior to firing a real request.\n";
return true;
}
void Proxy_Request(void* p)
{
Proxy* pp = (Proxy*)p;
if (CheckAccess(pp))
{
pp->real_subject_->base.Request(pp);
LogAccess(pp);
}
}
void Proxy_Init(Proxy * Proxy,RealSubject* real_subject)
{
Proxy->real_subject_ = real_subject;
Proxy->base.Request = Proxy_Request;
}
void ClientCode(Subject *s)
{
s->Request(s);
}
void Proxy_C()
{
std::cout << "Client: Executing the client code with a real subject:\n";
RealSubject rs;
RealSubject_Init(&rs, RealSubject_Request);
ClientCode(&rs.base);
std::cout << "\n";
std::cout << "Client: Executing the same client code with a proxy:\n";
Proxy px;
Proxy_Init(&px, &rs);
ClientCode(&px.base);
}
运行结果
责任链模式
责任链模式的介绍: https://refactoringguru.cn/design-patterns/chain-of-responsibility
责任链模式的C++实现: https://refactoringguru.cn/design-patterns/chain-of-responsibility/cpp/example
这个设计模式比较复杂,简单说
就是通过链式关系接力做一件事情,属于你的责任范围的活,你做,不是你的,传递到下一个链条上的对象
这个C++写思路是比较清晰的,通过方法重写,继承来实现统一方法链式调用
但是C语言写就比较复杂了,模拟C++ This指针的行为确实是花了一番功夫
我这里是额外加了一个AbstractHandler 指针来记录链式调用关系中的下一跳的地址
#include <iostream>
#include "string.h"
#include "stdio.h"
#include <string>
#include <vector>
struct Handler;
typedef struct Handler
{
Handler* (*SetNext)(void * _this,Handler* handler);
std::string(*Handle)(void* _this,std::string request);
}Handler;
typedef std::string(*HandlerFuncPtr)(void* _this, std::string request);
struct AbstractHandler;
typedef struct AbstractHandler
{
Handler base;
Handler* next_handler_;
AbstractHandler* next_abs;//额外添加的下一跳地址
}AbstractHandler;
Handler* SetNext(void* _this, Handler* handler)
{
AbstractHandler* p = (AbstractHandler*)_this;
p->next_handler_ = handler;
return handler;
}
std::string Handle(void* _this, std::string request)
{
AbstractHandler* p = (AbstractHandler*)_this;
if (p->next_handler_!=nullptr)
{
return p->next_handler_->Handle(p->next_abs,request);
}
return "";
}
void AbstractHandler_Init(AbstractHandler *a, HandlerFuncPtr f)
{
a->base.Handle = f;
a->base.SetNext = SetNext;
a->next_handler_ = NULL;
}
typedef struct
{
AbstractHandler base;
}MonkeyHandler;
typedef struct
{
AbstractHandler base;
}SquirrelHandler;
typedef struct
{
AbstractHandler base;
}DogHandler;
std::string MonkeyHandle(void* _this, std::string request)
{
if (request == "Banana") {
return "Monkey: I'll eat the " + request + ".\n";
}
else {
//不是的传递给下一个
AbstractHandler* p = (AbstractHandler*)_this;
return Handle(p, request);
}
}
std::string SquirrelHandle(void* _this, std::string request)
{
if (request == "Nut") {
return "Squirrel: I'll eat the " + request + ".\n";
}
else {
//不是的传递给下一个
AbstractHandler* p = (AbstractHandler*)_this;
return Handle(p, request);
}
}
std::string DogHandle(void* _this, std::string request)
{
if (request == "MeatBall") {
return "Dog: I'll eat the " + request + ".\n";
}
else {
//不是的传递给下一个
AbstractHandler* p = (AbstractHandler*)_this;
return Handle(p,request);
}
}
void ClientCode(AbstractHandler* p,Handler* handler)
{
std::vector<std::string> food = { "Nut", "Banana", "Cup of coffee" };
for (const std::string& f : food) {
std::cout << "Client: Who wants a " << f << "?\n";
const std::string result = handler->Handle(p,f);
if (!result.empty()) {
std::cout << " " << result;
}
else {
std::cout << " " << f << " was left untouched.\n";
}
}
}
void chain_of_responsibilityC()
{
MonkeyHandler m;
DogHandler d;
SquirrelHandler s;
//AbstractHandler_Init(&m.base, MonkeyHandle);
//AbstractHandler_Init(&d.base, DogHandle);
//AbstractHandler_Init(&s.base, SquirrelHandle);
m.base.base.Handle = MonkeyHandle;
m.base.base.SetNext = SetNext;
m.base.next_handler_ = NULL;
d.base.base.Handle = DogHandle;
d.base.base.SetNext = SetNext;
d.base.next_handler_ = NULL;
s.base.base.Handle = SquirrelHandle;
s.base.base.SetNext = SetNext;
s.base.next_handler_ = NULL;
m.base.base.SetNext(&m.base, &s.base.base);
m.base.next_abs = &s.base;
s.base.base.SetNext(&s.base, &d.base.base);
s.base.next_abs = &d.base;
//m.base.base.SetNext(&m.base, &d.base.base)->SetNext(&s.base, &s.base.base);
//std::cout << "Monkey->Squirrel->Dog\r\n";
ClientCode(&m.base, &m.base.base);
//std::cout << "Squirrel->Dog\r\n";
ClientCode(&s.base, &s.base.base);
}
运行效果
命令模式
命令模式的介绍: https://refactoringguru.cn/design-patterns/command
命令模式的C++实现: https://refactoringguru.cn/design-patterns/command/cpp/example
这个设计模式,怎么说呢
就是把函数指针封装,做成对象,可以在方法中用参数传递,然后通过对象的指针间接的去调用函数指针指向的函数
这个配合C++用真是特别流畅,写起来很舒服。
如果换成C语言来写,这个也是需要额外的加一个指针来模拟This指针的行为,保证传递进函数的参数是正确的参数
#include <iostream>
typedef struct
{
void (*Execute)(void*);
void* payload;//这里存放这个命令派生出来的子类的指针
}Command;
typedef struct
{
Command base_command_;
std::string pay_load_;
}SimpleCommand;
void SimpleCommand_Execute(void* p)
{
SimpleCommand* _p = (SimpleCommand*)p;
std::cout << "SimpleCommand: See, I can do simple things like printing ("
<< _p->pay_load_ << ")\n";
}
void SimpleCommand_Init(SimpleCommand* s, std::string pay_load_)
{
s->base_command_.payload = (void*)s;
s->base_command_.Execute = SimpleCommand_Execute;
s->pay_load_ = pay_load_;
}
typedef struct
{
void (*DoSomething)(const std::string a);
void (*DoSomethingElse)(const std::string a);
}Receiver;
void Receiver_DoSomething(const std::string a) {
std::cout << "Receiver: Working on (" << a << ".)\n";
}
void Receiver_DoSomethingElse(const std::string a) {
std::cout << "Receiver: Also working on (" << a << ".)\n";
}
void Receiver_Init(Receiver *p)
{
p->DoSomething = Receiver_DoSomething;
p->DoSomethingElse = Receiver_DoSomethingElse;
}
typedef struct
{
Command base_command_;
Receiver* receiver_;
std::string a_;
std::string b_;
}ComplexCommand;
void ComplexCommand_Execute(void *p)
{
ComplexCommand* _this = (ComplexCommand*)p;
std::cout << "ComplexCommand: Complex stuff should be done by a receiver object.\n";
_this->receiver_->DoSomething(_this->a_);
_this->receiver_->DoSomethingElse(_this->b_);
}
void ComplexCommand_Init(ComplexCommand* c, Receiver* receiver, std::string a, std::string b)
{
c->a_ = a;
c->b_ = b;
c->base_command_.Execute = ComplexCommand_Execute;
c->base_command_.payload = (void*)c;
c->receiver_ = receiver;
}
typedef struct
{
Command* on_start_;
Command* on_finish_;
}Invoker;
void SetOnStart(Invoker *i,Command*c,void *payload)
{
i->on_start_ = c;
i->on_start_->payload = payload;
}
void SetOnFinish(Invoker* i, Command* c, void* payload)
{
i->on_finish_ = c;
i->on_finish_->payload = payload;
}
void DoSomethingImportant(Invoker* _this)
{
std::cout << "Invoker: Does anybody want something done before I begin?\n";
if (_this->on_start_) {
//这样入参的时候才能在对应的函数指针里面得到正确的变量
_this->on_start_->Execute(_this->on_start_->payload);
}
std::cout << "Invoker: ...doing something really important...\n";
std::cout << "Invoker: Does anybody want something done after I finish?\n";
if (_this->on_finish_) {
_this->on_finish_->Execute(_this->on_finish_->payload);
}
}
void CommandC()
{
Invoker invoker;
SimpleCommand sc;
ComplexCommand cc;
Receiver receiver;
SimpleCommand_Init(&sc, "Say Hi!");
Receiver_Init(&receiver);
ComplexCommand_Init(&cc, &receiver, "Send email", "Save report");
SetOnStart(&invoker, &sc.base_command_, &sc);
SetOnFinish(&invoker, &cc.base_command_, &cc);
DoSomethingImportant(&invoker);
}
运行结果:
迭代器
迭代器模式的介绍: https://refactoringguru.cn/design-patterns/iterator
迭代器模式的C++实现: https://refactoringguru.cn/design-patterns/iterator/cpp/example
这个很好理解,就是对于集合类(链表,图,树等)的对象,应该提供一个接口给用户,不需要暴露内部实现的方式,遍历其中的存放的值
它C++例程用的是模板做的,C语言不好做模板,我这里参考了之前看过的dyad库(一个C语言实现的简单的TCP组件)的动态数组弄法,它内部通过一系列的宏定义,实现了模板的特性。我用这个部分代码,改了一改,做了个类似于它C++例子的效果出来。这里迭代器,我采用多态的设计思想,无论是哪种模板类的对象,都应该实现Init,IsDone,Next,Current这四个接口。
#include <iostream>
#include <string>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//这里借用了dyad[一个单文件的C语言实现的简单的TCP库]中动态数组的实现方法
//借用宏的方式实现了类似C++中模板的感觉
//dyad动态数组
//内存部分
//动态申请
static void* dyad_realloc(void* ptr, int n)
{
ptr = realloc(ptr, n);
if ((!ptr) && (n != 0))
{
printf("out of mem!!\r\n");
exit(-1);
}
return ptr;
}
//动态释放
static void dayd_free(void* ptr)
{
free(ptr);
}
//动态数组
//扩展
static void vec_expand(char** data,int* length, int* capacity, int memsz)
{
if (*length + 1 > *capacity)
{
if (*capacity == 0)
{
*capacity = 1;
}
else
{
*capacity <<= 1;//容量翻倍
}
*data =(char *) dyad_realloc(*data, *capacity * memsz);
}
}
#define Vec(T)\
struct { T *data; int length, capacity; }
#define Iterator(T)\
struct {T m_it_; void * vec_; }
#define vec_unpack(v)\
(char**)&(v)->data, &(v)->length, &(v)->capacity, sizeof(*(v)->data)
#define vec_init(v)\
memset((v), 0, sizeof(*(v)))
#define vec_deinit(v)\
dyad_free((v)->data)
#define vec_clear(v)\
((v)->length = 0)
#define vec_push(v, val)\
( vec_expand(vec_unpack(v)),\
(v)->data[(v)->length++] = (val) )
#define vec_splice(v, start, count)\
( vec_splice(vec_unpack(v), start, count),\
(v)->length -= (count) )
typedef struct
{
Vec(int) _vec;
}_VectorInt;
typedef struct
{
Iterator(int) _iter;
}_VectorIntInterator;
typedef struct
{
void(*Init)(void* Interator, void* Vector);
bool(*IsDone)(void* Interator);
void(*Next)(void* Interator);
void* (*Current)(void* Interator);
}InteratorUtils;
void VectorIntInterator_Init(void* Interator, void* Vector)
{
_VectorIntInterator* i =(_VectorIntInterator*)Interator;
_VectorInt* v = (_VectorInt*)Vector;
i->_iter.m_it_ = 0;
i->_iter.vec_ = v;
}
bool VectorIntIterator_IsDone(void* Interator )
{
_VectorIntInterator* i = (_VectorIntInterator*)Interator;
_VectorInt* it = (_VectorInt*)(i->_iter.vec_);
return i->_iter.m_it_ == it->_vec.length;
}
void VectorIntIterator_Next(void* Interator)
{
_VectorIntInterator* i = (_VectorIntInterator*)Interator;
_VectorInt* it = (_VectorInt*)(i->_iter.vec_);
if(i->_iter.m_it_<it->_vec.capacity)
i->_iter.m_it_++;
}
void* VectorIntIterator_Current(void* Interator)
{
_VectorIntInterator* i = (_VectorIntInterator*)Interator;
_VectorInt* it = (_VectorInt*)(i->_iter.vec_);
return (void*) & (it->_vec.data[i->_iter.m_it_]);
}
typedef struct
{
_VectorInt v;
_VectorIntInterator iterator;
InteratorUtils util;
}Vector_Int;
void Vector_Int_Init(Vector_Int * _this)
{
vec_init(&_this->v._vec);
VectorIntInterator_Init(&_this->iterator, &_this->v);
_this->util.Current = VectorIntIterator_Current;
_this->util.Init = VectorIntInterator_Init;
_this->util.IsDone = VectorIntIterator_IsDone;
_this->util.Next = VectorIntIterator_Next;
}
void Vector_Int_Add(Vector_Int* _this,int data)
{
vec_push(&_this->v._vec, data);
}
void IteratorC()
{
Vector_Int vec;
Vector_Int_Init(&vec);
for (int i = 0; i < 10; i++)
{
Vector_Int_Add(&vec, i);
}
while (!vec.util.IsDone(&vec.iterator))
{
int* ptr = (int*)vec.util.Current(&vec.iterator);
printf("%d\r\n", *ptr);
vec.util.Next(&vec.iterator);
}
}
运行效果:
中介者模式
中介者模式的介绍: https://refactoringguru.cn/design-patterns/mediator
中介者模式的C++实现: https://refactoringguru.cn/design-patterns/mediator/cpp/example
简单说
这种设计模式就是将对不同对象的请求与操作,统一由一个“中间人”来执行调度,避免各种对象之间直接通信,造成的强耦合。
C++的范例代码是比较好理解的,换成C语言来做的话,主要是要考虑模仿this指针的行为
这里也是采用了void指针来模拟C++ This指针的行为
#include <iostream>
#include <string>
struct BaseComponent;
typedef struct
{
void (*Notify)(BaseComponent* sender, std::string event,void *);
}Mediator;
typedef struct BaseComponent
{
Mediator* mediator_;
}BaseComponent;
void BaseComponent_Set_Medaitor(BaseComponent *b, Mediator* mediator)
{
b->mediator_ = mediator;
}
typedef struct
{
BaseComponent _baseComponent;
}Component1;
typedef struct
{
BaseComponent _baseComponent;
}Component2;
typedef struct
{
Mediator _mediator;
Component1* _Component1;
Component2* _Component2;
}ConcreteMediator;
void DoA(Component1* c, void*p)
{
ConcreteMediator* cm = (ConcreteMediator*)p;
std::cout << "Component 1 does A.\n";
c->_baseComponent.mediator_->Notify(&c->_baseComponent, "A", cm);
}
void DoB(Component1* c, void* p)
{
ConcreteMediator* cm = (ConcreteMediator*)p;
std::cout << "Component 1 does B.\n";
c->_baseComponent.mediator_->Notify(&c->_baseComponent, "B", cm);
}
void DoC(Component2* c, void* p)
{
ConcreteMediator* cm = (ConcreteMediator*)p;
std::cout << "Component 2 does C.\n";
c->_baseComponent.mediator_->Notify(&c->_baseComponent, "C",cm);
}
void DoD(Component2* c, void* p)
{
ConcreteMediator* cm = (ConcreteMediator*)p;
std::cout << "Component 2 does D.\n";
c->_baseComponent.mediator_->Notify(&c->_baseComponent, "D", cm);
}
void Notify(BaseComponent* sender, std::string event,void *p)
{
ConcreteMediator* cm = (ConcreteMediator*)p;
if (event == "A") {
std::cout << "Mediator reacts on A and triggers following operations:\n";
DoC(cm->_Component2, cm);
}
if (event == "D") {
std::cout << "Mediator reacts on D and triggers following operations:\n";
DoB(cm->_Component1, cm);
DoC(cm->_Component2, cm);
}
}
void ConcreteMediator_Init(
ConcreteMediator * cm,
Component1* _Component1,
Component2* _Component2)
{
cm->_Component1 = _Component1;
cm->_Component2 = _Component2;
cm->_mediator.Notify = Notify;
BaseComponent_Set_Medaitor(&cm->_Component1->_baseComponent,
&cm->_mediator);
BaseComponent_Set_Medaitor(&cm->_Component2->_baseComponent,
&cm->_mediator);
}
void mediatorC()
{
Component1 c1;
Component2 c2;
ConcreteMediator mediator;
ConcreteMediator_Init(&mediator, &c1, &c2);
std::cout << "Client triggers operation A.\n";
DoA(&c1, &mediator);
std::cout << "\n";
std::cout << "Client triggers operation D.\n";
DoD(&c2, &mediator);
}
运行结果: