书接上回

由于内容太多,编辑器太卡了,所以分P了
上P在这里

目录

  • 书接上回
    • 备忘录模式
    • 观察者模式
    • 状态模式
    • 策略模式
    • 模板方法模式
    • 访问者模式

备忘录模式

备忘录模式的介绍: https://refactoringguru.cn/design-patterns/memento
备忘录模式的C++实现: https://refactoringguru.cn/design-patterns/memento/cpp/example
这个模式还是挺复杂的
大概的套路就是这样
原发者自己有保存状态和恢复状态的接口
负责人做一个统筹,它有一个指针指向待处理的原发者
它自己的备份和恢复接口内部就调用原发者提供的接口,保存原发者状态到备忘录或者恢复备忘录到原发者(通过创建备忘录类)

C++的代码相对还是好理解的,如果换C语言来写,还是比较复杂的,涉及到动态内存,模拟String功能
我通过dyad库的动态模板数据类型,做了一个简单的string库

#include <iostream>
#include <string>
#include <vector>
#pragma warning(disable:4996)//这里借用了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 dyad_free(void* ptr)
{free(ptr);
}//动态数组#define Vec(T)\struct { T *data; int length, capacity; }#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) )//扩展
static void vec_expand(char** data, int* length, int* capacity, int memsz)
{int before = 0;if (*length + 1 > *capacity){before = *capacity;if (*capacity == 0){*capacity = 1;}else{*capacity <<= 1;//容量翻倍}*data = (char*)dyad_realloc(*data, *capacity * memsz);//注意清空额外申请出来的内存memset(*data + before, 0, *capacity / 2);}
}/// <summary>
/// 模拟字符串
/// </summary>
typedef struct
{Vec(char) _vec;
}SimString;//字符串初始化
void SimString_Init(SimString* p, const char* str)
{vec_init(&p->_vec);for (int i = 0; i < strlen(str); i++){vec_push(&p->_vec, str[i]);}
}//获取字符串
void SimString_Get(SimString* p, char* str)
{for (int i = 0; i < p->_vec.length; i++){str[i] = p->_vec.data[i];}
}//截取字符串
void SimString_Splice(SimString* p, char* str,int start,int end)
{if ((start < p->_vec.length) && (end < p->_vec.length) &&(start<end)){int i = 0;for ( i= start; i < end; i++){str[i] = p->_vec.data[i];}//添加结束符str[i] = '\0';}
}//拼接
void SimString_Cat(SimString* p, const char* str)
{for (int i = 0; i < strlen(str); i++){vec_push(&p->_vec, str[i]);}
}/// <summary>
/// 打印字符串
/// </summary>
/// <param name="p"></param>
void SimString_Print(SimString* p)
{printf("%s\r\n",p->_vec.data);}/// <summary>
/// 输出指定长度的字符串
/// </summary>
/// <param name="p"></param>
/// <param name="len"></param>
void SimString_Show(SimString* p, int start,int end)
{for (int i = start; (i<p->_vec.length)&&(i < end); i++){printf("%c", p->_vec.data[i]);}printf("\r\n");
}/// <summary>
/// 拷贝字符串
/// </summary>
/// <param name="dst"></param>
/// <param name="src"></param>
void SimString_Copy(SimString* dst, SimString* src)
{vec_init(&dst->_vec);for (int i = 0; i < src->_vec.length; i++){vec_push(&dst->_vec, src->_vec.data[i]);}
}/typedef SimString(*FuncPtr)(void*);
typedef struct
{FuncPtr GetName;FuncPtr date;FuncPtr state;
}Memento;typedef struct
{Memento _memento;SimString state_;SimString date_;
}ConcreteMemento;SimString ConcreteMemento_date(void* p);
SimString ConcreteMemento_GetName(void* p);
SimString ConcreteMemento_state(void* p);/// <summary>
/// 初始化
/// </summary>
/// <param name="p"></param>
/// <param name="state"></param>
void ConcreteMemento_Init(ConcreteMemento* p, const char* state)
{SimString_Init(&p->state_, state);p->_memento.date = ConcreteMemento_date;p->_memento.state = ConcreteMemento_state;p->_memento.GetName = ConcreteMemento_GetName;time_t current_time;char* c_time_string;/* Get the current time */current_time = time(NULL);/* Convert to local time format */c_time_string = ctime(&current_time);SimString_Init(&p->date_, c_time_string);
}/// <summary>
/// 返回状态
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
SimString ConcreteMemento_state(void*p)
{ConcreteMemento* pp = (ConcreteMemento*)p;return pp->state_;
}/// <summary>
/// 获取名字
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
SimString ConcreteMemento_GetName(void* p)
{ConcreteMemento* pp = (ConcreteMemento*)p;SimString* ret = (SimString*)malloc(sizeof(SimString));SimString_Init(ret, pp->date_._vec.data);SimString_Cat(ret, "-/-(");char* tmp = (char*)malloc(50);SimString_Splice(&pp->state_, tmp, 0, 9);SimString_Cat(ret, tmp);SimString_Cat(ret, "...)");free(tmp);return *ret;
}/// <summary>
/// 获取日期
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
SimString ConcreteMemento_date(void* p)
{ConcreteMemento* pp = (ConcreteMemento*)p;return pp->date_;
}/// <summary>
/// 删除
/// </summary>
/// <param name="p"></param>
void ConcreteMemento_Dele(ConcreteMemento* p)
{vec_deinit(&p->date_._vec);vec_deinit(&p->state_._vec);
}typedef struct
{SimString state_;
}Originator;/// <summary>
/// 初始化
/// </summary>
/// <param name="p"></param>
/// <param name="state"></param>
void Originator_Init(Originator*p, const char * state)
{SimString_Init(&p->state_, state);std::cout << "被记录者: 我的初始状态是: " ;SimString_Print(&p->state_);
}/// <summary>
/// 删除
/// </summary>
/// <param name="p"></param>
void Originator_Del(Originator* p)
{vec_deinit(&p->state_._vec);
}/// <summary>
/// 随机字符串
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
std::string GenerateRandomString(int length) {const char alphanum[] ="0123456789""ABCDEFGHIJKLMNOPQRSTUVWXYZ""abcdefghijklmnopqrstuvwxyz";int stringLength = sizeof(alphanum) - 1;std::string random_string;for (int i = 0; i < length; i++) {random_string += alphanum[std::rand() % stringLength];}return random_string;
}/// <summary>
/// 做事
/// </summary>
/// <param name="p"></param>
void Originator_DoSomething(Originator* p)
{std::cout << "被记录者: 我希望做些重要的事情\n";SimString_Init( &p->state_ ,GenerateRandomString(30).c_str());std::cout << "被记录者: 然后我的状态发生变化了: " ;SimString_Print(&p->state_);}/// <summary>
/// 保存
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
Memento* Originator_Save(Originator* p)
{char* tmp = (char*)malloc(50);ConcreteMemento* pp = (ConcreteMemento*)malloc(sizeof(ConcreteMemento));SimString_Get(&p->state_, tmp);ConcreteMemento_Init(pp, tmp);free(tmp);return (Memento*)(pp);
}/// <summary>
/// 恢复
/// </summary>
/// <param name="p"></param>
/// <param name="memento"></param>
void Originator_Restore(Originator* p,Memento* memento)
{   ConcreteMemento* pp = (ConcreteMemento*)memento;SimString* tmp = (SimString*)malloc(sizeof(SimString));SimString_Init(tmp, "xxx");SimString_Copy(&pp->state_,tmp);std::cout << "被记录者: 我的状态发生变化了: \r\n";SimString_Print(&p->state_);
}typedef struct
{std::vector<Memento*> mementos_;Originator* originator_;
}Caretaker;/// <summary>
/// 初始化
/// </summary>
/// <param name="p"></param>
/// <param name="o"></param>
void Caretaker_Init(Caretaker* p, Originator* o)
{p->originator_ = o;
}/// <summary>
/// 删除
/// </summary>
/// <param name="p"></param>
void Caretaker_Dele(Caretaker* p)
{for (auto m : p->mementos_) delete m;
}/// <summary>
/// 备份
/// </summary>
/// <param name="p"></param>
void Caretaker_Backup(Caretaker* p)
{std::cout << "\n负责人: 正在保存当前状态...\n";p->mementos_.push_back(Originator_Save(p->originator_));
}/// <summary>
/// 撤销
/// </summary>
/// <param name="p"></param>
void Caretaker_Undo(Caretaker* p) {if (!p->mementos_.size()) {return;}Memento* memento = p->mementos_.back();p->mementos_.pop_back();std::cout << "负责人: 把状态恢复到: ";SimString* tmp = (SimString*)malloc(sizeof(SimString));*tmp = (ConcreteMemento_GetName(memento));SimString_Print(tmp);Originator_Restore(p->originator_,memento);free(tmp);
}/// <summary>
/// 显示历史
/// </summary>
/// <param name="p"></param>
void Caretaker_ShowHistory(Caretaker* p)
{std::cout << "负责人: 这是目前的记录:\n";for (Memento* memento : p->mementos_) {SimString* tmp = (SimString*)malloc(sizeof(SimString));* tmp = (ConcreteMemento_GetName(memento));SimString_Print(tmp);free(tmp);}
}void mementoC()
{Originator originator;Caretaker caretaker;Originator_Init(&originator, "Super-duper-super-puper-super.");Caretaker_Init(&caretaker, &originator);Caretaker_Backup(&caretaker);Originator_DoSomething(&originator);Caretaker_Backup(&caretaker);Originator_DoSomething(&originator);Caretaker_Backup(&caretaker);Originator_DoSomething(&originator);Caretaker_ShowHistory(&caretaker);std::cout << "\n客户端: 现在开始回滚!\n\n";Caretaker_Undo(&caretaker);std::cout << "\n客户端: 现在开始回滚!\n\n";Caretaker_Undo(&caretaker);Originator_Del(&originator);Caretaker_Dele(&caretaker);}

运行结果:

观察者模式

观察者模式的介绍: https://refactoringguru.cn/design-patterns/observer
观察者模式的C++实现: https://refactoringguru.cn/design-patterns/observer/cpp/example
这个观察者模式也是挺复杂的
就是观察者内部存在一个指针(C++里是一个引用),这个指针记录着需要观察的对象
被观察者在执行“通知”操作后,会“通知”到所有的观察者
如果不希望观察了,观察者提供一个接口,可以移除需要被观察的对象,移除被观察者中记录观察者表对象信息的记录。
观察者都持有同样的“更新”接口,被观察者拥有同样的“附加”,“移除”,“通知”接口
C++实现还是相对清晰的,C实现就会比较绕,没有引用和This指针就得换其他的方式模式出来
上代码:

#include <iostream>
#include <list>
#include <string>//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 dyad_free(void* ptr)
{free(ptr);
}//动态数组#define Vec(T)\struct { T *data; int length, capacity; }#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) )//扩展
static void vec_expand(char** data, int* length, int* capacity, int memsz)
{int before = 0;if (*length + 1 > *capacity){before = *capacity;if (*capacity == 0){*capacity = 1;}else{*capacity <<= 1;//容量翻倍}*data = (char*)dyad_realloc(*data, *capacity * memsz);//注意清空额外申请出来的内存memset(*data + before, 0, *capacity / 2);}
}/// <summary>
/// 模拟字符串
/// </summary>
typedef struct
{Vec(char) _vec;
}SimString;//字符串初始化
static void SimString_Init(SimString* p, const char* str)
{vec_init(&p->_vec);for (int i = 0; i < strlen(str); i++){vec_push(&p->_vec, str[i]);}
}//获取字符串
static void SimString_Get(SimString* p, char* str)
{for (int i = 0; i < p->_vec.length; i++){str[i] = p->_vec.data[i];}
}//截取字符串
static void SimString_Splice(SimString* p, char* str, int start, int end)
{if ((start < p->_vec.length)&& (end < p->_vec.length)&& (start < end)){int i = 0;for (i = start; i < end; i++){str[i] = p->_vec.data[i];}//添加结束符str[i] = '\0';}
}//拼接
static void SimString_Cat(SimString* p, const char* str)
{for (int i = 0; i < strlen(str); i++){vec_push(&p->_vec, str[i]);}
}/// <summary>
/// 打印字符串
/// </summary>
/// <param name="p"></param>
static void SimString_Print(SimString* p)
{printf("%s\r\n", p->_vec.data);}/// <summary>
/// 输出指定长度的字符串
/// </summary>
/// <param name="p"></param>
/// <param name="len"></param>
static void SimString_Show(SimString* p, int start, int end)
{for (int i = start; (i < p->_vec.length) && (i < end); i++){printf("%c", p->_vec.data[i]);}printf("\r\n");
}/// <summary>
/// 拷贝字符串
/// </summary>
/// <param name="dst"></param>
/// <param name="src"></param>
static void SimString_Copy(SimString* dst, SimString* src)
{vec_init(&dst->_vec);for (int i = 0; i < src->_vec.length; i++){vec_push(&dst->_vec, src->_vec.data[i]);}
}/typedef void(*Update)(void * p,SimString mess);
typedef struct
{Update _update;
}IObserver;typedef void (*Attach)(void* p, IObserver* observer);
typedef void (*Detach)(void* p, IObserver* observer);
typedef void (*Notify)(void* p);
typedef struct
{Attach _attach;Detach _detach;Notify _notify;
}ISubject;typedef struct
{ISubject _isubject;std::list<IObserver*> list_observer_;SimString message_;
}Subject;void Subject_Attach(void* p, IObserver* observer);
void Subject_Detach(void* p, IObserver* observer);
void Subject_Notify(void* p);void Subject_Init(Subject* p)
{p->_isubject._attach = Subject_Attach;p->_isubject._detach = Subject_Detach;p->_isubject._notify = Subject_Notify;SimString_Init(&p->message_,"xxx");
}
void Subject_DeInit(Subject* p)
{std::cout << "Goodbye, I was the Subject.\n";
}void Subject_Attach(void* p, IObserver* observer)
{Subject* pp = (Subject*)p;pp->list_observer_.push_back(observer);
}void Subject_Detach(void* p, IObserver* observer)
{Subject* pp = (Subject*)p;pp->list_observer_.remove(observer);
}void HowManyObserver(Subject *s) {std::cout << "There are " << s->list_observer_.size() << " observers in the list.\n";
}void Subject_Notify(void* p)
{Subject* pp = (Subject*)p;//通知所有观察者std::list<IObserver*>::iterator iterator = pp->list_observer_.begin();HowManyObserver(pp);while (iterator != pp->list_observer_.end()) {(*iterator)->_update((*iterator), pp->message_);++iterator;}
}void Subject_CreateMessage(Subject* s,const char * mes)
{SimString_Init(&s->message_, mes);Subject_Notify(s);
}void SomeBusinessLogic(Subject* s) {SimString_Init(&s->message_, "change message message");s->_isubject._notify(s);std::cout << "I'm about to do some thing important\n";
}typedef struct
{IObserver _iobserver;SimString message_from_subject_;Subject * subject_;int static_number_;int number_;
}Observer;void Observer_Update(void* p, SimString mess);
static int num = 0;
void Observer_Init(Observer *p,Subject*s)
{num++;p->_iobserver._update = Observer_Update;p->subject_ = s;p->subject_->_isubject._attach = Subject_Attach;p->subject_->_isubject._detach = Subject_Detach;p->subject_->_isubject._notify = Subject_Notify;p->subject_->list_observer_ = s->list_observer_;SimString_Copy(&p->subject_->message_, &s->message_);p->subject_->_isubject._attach = s->_isubject._attach;p->subject_->_isubject._detach = s->_isubject._detach;p->subject_->_isubject._notify = s->_isubject._notify;p->subject_->_isubject._attach(s, &p->_iobserver);p->number_ = num;p->static_number_ = num;std::cout << "Hi, I'm the Observer \"" <<p->static_number_ << "\".\n";
}void Observer_DeInit(Observer* p)
{std::cout << "Goodbye, I was the Observer \"" << p->number_ << "\".\n";
}void PrintInfo(Observer* p) {std::cout << "Observer \""<< p->number_ << "\": a new message is available --> ";SimString_Print(&p->message_from_subject_);}
void Observer_Update(void* p, SimString mess)
{Observer* pp = (Observer*)p;SimString_Init(&pp->message_from_subject_, mess._vec.data);PrintInfo(pp);
}void Observer_RemoveMeFromTheList(Observer* p) {p->subject_->_isubject._detach(p->subject_,&p->_iobserver);std::cout << "Observer \"" << p->number_ << "\" removed from the list.\n";
}static void ClientCode()
{Subject subject;Subject_Init(&subject);Observer ob1,ob2,ob3,ob4,ob5;Observer_Init(&ob1,&subject);Observer_Init(&ob2, &subject);Observer_Init(&ob3, &subject);Subject_CreateMessage(&subject, "Hello World! :D");Observer_RemoveMeFromTheList(&ob3);Subject_CreateMessage(&subject, "The weather is hot today! :p");Observer_Init(&ob4, &subject);Observer_RemoveMeFromTheList(&ob2);Observer_Init(&ob5, &subject);Subject_CreateMessage(&subject, "My new car is great! ;)");Observer_RemoveMeFromTheList(&ob5);Observer_RemoveMeFromTheList(&ob4);Observer_RemoveMeFromTheList(&ob1);Observer_DeInit(&ob1);Observer_DeInit(&ob2);Observer_DeInit(&ob3);Observer_DeInit(&ob4);Observer_DeInit(&ob5);Subject_DeInit(&subject);
}void ObserverC() {ClientCode();
}

状态模式

状态模式的介绍: https://refactoringguru.cn/design-patterns/state/
状态模式的C++实现: https://refactoringguru.cn/design-patterns/state/cpp/example

类似于状态机的实现方式
它不同于那种Switch-case实现或者if嵌套实现的方式
它用的是函数指针的方式进行切换
它的设计理念是在状态基类的定义里面放置上下文切换对象的指针
与其对应的是上下文切换对象里面存在指向状态基类的指针

具体的状态继承状态基类

套路大概就是这样,换成C语言实现看看

C语言实现的代码

#include <stdio.h>
#include <string.h>
#include <iostream>struct Context;typedef struct
{Context* context_;void (*Handel1)(void*);void (*Handel2)(void*);
}State;void State_Set_Context(State* state, Context* context)
{state->context_ = context;
}typedef struct Context
{State* state_;
}Context;void Context_TransitionTo(Context* _this, State* state)
{std::cout << "Context: Transition to " << typeid(*state).name() << ".\n";if (_this->state_ != nullptr){_this->state_ = nullptr;free(_this->state_);}_this->state_ = state;State_Set_Context(_this->state_, _this);
}void Context_Init(Context* p, State* state)
{Context_TransitionTo(p, state);
}void Context_Request1(Context* p)
{p->state_->Handel1(p->state_);
}void Context_Request2(Context* p)
{p->state_->Handel2(p->state_);
}typedef struct
{State _base;
}ConcreteStateA;typedef struct
{State _base;
}ConcreteStateB;
void ConcreteStateA_Handle1(void* p);
void ConcreteStateA_Handle2(void* p);void ConcreteStateB_Handle1(void* p);
void ConcreteStateB_Handle2(void* p);
void ConcreteStateA_Init(ConcreteStateA *p)
{p->_base.context_ = NULL;p->_base.Handel1 = ConcreteStateA_Handle1;p->_base.Handel2 = ConcreteStateA_Handle2;
}
void ConcreteStateB_Init(ConcreteStateB* p)
{p->_base.context_ = NULL;p->_base.Handel1 = ConcreteStateB_Handle1;p->_base.Handel2 = ConcreteStateB_Handle2;
}void ConcreteStateA_Handle1(void* p)
{ConcreteStateA* pp = (ConcreteStateA*)p;ConcreteStateB* ppp = (ConcreteStateB*)malloc(sizeof(ConcreteStateB));ConcreteStateB_Init(ppp);std::cout << "ConcreteStateA handles request1.\n";std::cout << "ConcreteStateA wants to change the state of the context.\n";Context_TransitionTo(pp->_base.context_, &ppp->_base);
}void ConcreteStateA_Handle2(void*p)
{std::cout << "ConcreteStateA handles request2.\n";
}void ConcreteStateB_Handle1(void* p)
{std::cout << "ConcreteStateB handles request1.\n";
}void ConcreteStateB_Handle2(void* p)
{ConcreteStateB* pp = (ConcreteStateB*)p;ConcreteStateA* ppp = (ConcreteStateA*)malloc(sizeof(ConcreteStateA));ConcreteStateA_Init(ppp);std::cout << "ConcreteStateB handles request2.\n";std::cout << "ConcreteStateB wants to change the state of the context.\n";Context_TransitionTo(pp->_base.context_, &ppp->_base);
}void StateC()
{Context context;context.state_ = (State*)malloc(sizeof(State));context.state_->context_ = NULL;context.state_->Handel1= NULL;context.state_->Handel2 = NULL;ConcreteStateA StateA;ConcreteStateA_Init(&StateA);Context_Init(&context, &StateA._base);Context_Request1(&context);Context_Request2(&context);
}

运行结果

策略模式

策略模式的介绍: https://refactoringguru.cn/design-patterns/strategy/
策略模式的C++实现: https://refactoringguru.cn/design-patterns/strategy/cpp/example
这个设计模式就是将不同方法抽象出一个公共的接口
然后客户端存在一个接口的指针,指向不同的方法(但是他们拥有相同的接口)
看懂了C++的代码之后,简化了下,做出了C语言的版本

#include <iostream>
#include <list>
#include <string>//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 dyad_free(void* ptr)
{free(ptr);
}//动态数组#define Vec(T)\struct { T *data; int length, capacity; }#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) )//扩展
static void vec_expand(char** data, int* length, int* capacity, int memsz)
{int before = 0;if (*length + 1 > *capacity){before = *capacity;if (*capacity == 0){*capacity = 1;}else{*capacity <<= 1;//容量翻倍}*data = (char*)dyad_realloc(*data, *capacity * memsz);//注意清空额外申请出来的内存memset(*data + before, 0, *capacity / 2);}
}/// <summary>
/// 模拟字符串
/// </summary>
typedef struct
{Vec(char) _vec;
}SimString;//字符串初始化
static void SimString_Init(SimString* p, const char* str)
{vec_init(&p->_vec);for (int i = 0; i < strlen(str); i++){vec_push(&p->_vec, str[i]);}
}//获取字符串
static void SimString_Get(SimString* p, char* str)
{for (int i = 0; i < p->_vec.length; i++){str[i] = p->_vec.data[i];}
}//截取字符串
static void SimString_Splice(SimString* p, char* str, int start, int end)
{if ((start < p->_vec.length)&& (end < p->_vec.length)&& (start < end)){int i = 0;for (i = start; i < end; i++){str[i] = p->_vec.data[i];}//添加结束符str[i] = '\0';}
}//拼接
static void SimString_Cat(SimString* p, const char* str)
{for (int i = 0; i < strlen(str); i++){vec_push(&p->_vec, str[i]);}
}/// <summary>
/// 打印字符串
/// </summary>
/// <param name="p"></param>
static void SimString_Print(SimString* p)
{printf("%s\r\n", p->_vec.data);}/// <summary>
/// 输出指定长度的字符串
/// </summary>
/// <param name="p"></param>
/// <param name="len"></param>
static void SimString_Show(SimString* p, int start, int end)
{for (int i = start; (i < p->_vec.length) && (i < end); i++){printf("%c", p->_vec.data[i]);}printf("\r\n");
}/// <summary>
/// 拷贝字符串
/// </summary>
/// <param name="dst"></param>
/// <param name="src"></param>
static void SimString_Copy(SimString* dst, SimString* src)
{vec_init(&dst->_vec);for (int i = 0; i < src->_vec.length; i++){vec_push(&dst->_vec, src->_vec.data[i]);}
}///策略接口
typedef struct
{SimString *(*doAlgorithm)(SimString * data);
}Strategy;typedef struct
{Strategy strategy_;
}Context;void Context_Init(Context* p)
{p->strategy_.doAlgorithm = NULL;
}void Context_set_strategy(Context* p, Strategy *s)
{p->strategy_ = *s;
}void Context_doSomeBusinessLogic(Context*p)
{if (p->strategy_.doAlgorithm != NULL){std::cout << "Context: Sorting data using the strategy (not sure how it'll do it)\n";SimString* s =(SimString*) malloc(sizeof(SimString));SimString_Init(s, "aecbd");SimString_Print(p->strategy_.doAlgorithm(s));vec_deinit(&s->_vec);free(s);}else{std::cout << "Context: Strategy isn't set\n";}
}typedef struct
{Strategy _base;
}ConcreteStrategyA;
SimString* ConcreteStrategyA_doAlgorithm(SimString* data);
void ConcreteStrategyA_Init(ConcreteStrategyA* p)
{p->_base.doAlgorithm = ConcreteStrategyA_doAlgorithm;
}
SimString *ConcreteStrategyA_doAlgorithm(SimString* data)
{SimString* tmp = (SimString*)malloc(sizeof(SimString));SimString_Copy(tmp, data);return tmp;
}typedef struct
{Strategy _base;
}ConcreteStrategyB;SimString* ConcreteStrategyB_doAlgorithm(SimString* data);
void ConcreteStrategyB_Init(ConcreteStrategyB *p)
{p->_base.doAlgorithm = ConcreteStrategyB_doAlgorithm;
}SimString * ConcreteStrategyB_doAlgorithm(SimString* data)
{SimString* tmp = (SimString*)malloc(sizeof(SimString));vec_init(&tmp->_vec);for (int i = data->_vec.length-1; i >= 0; i--){vec_push(&tmp->_vec, data->_vec.data[i]);}return tmp;
}void StrategyC()
{Context context;ConcreteStrategyA A;ConcreteStrategyA_Init(&A);ConcreteStrategyB B;ConcreteStrategyB_Init(&B);Context_Init(&context);Context_set_strategy(&context, &A._base);Context_doSomeBusinessLogic(&context);std::cout << "\n";std::cout << "Client: Strategy is set to reverse sorting.\n";Context_set_strategy(&context, &B._base);Context_doSomeBusinessLogic(&context);
}

运行结果:

模板方法模式

模板方法模式的介绍: https://refactoringguru.cn/design-patterns/template-method
模板方法模式的C++实现: https://refactoringguru.cn/design-patterns/template-method/cpp/example
这个设计模式就是将一个实现复杂方法拆分成小的步骤,步骤都使用固定的函数模板来实现,有些有固定实现,有些没有;具体的复杂方法都继承这个基类,重写基类的方法。

 #include <stdio.h>
#include <string>
#include <iostream>
#include <algorithm>typedef struct
{void (*BaseOperation1)(void*);void (*BaseOperation2)(void*);void (*BaseOperation3)(void*);void (*RequiredOperations1)(void*);void (*RequiredOperation2)(void*);void (*Hook1)(void*);void (*Hook2)(void*);
}AbstractClass;void TemplateMethod(AbstractClass *_this)
{_this->BaseOperation1(NULL);_this->RequiredOperations1(NULL);_this->BaseOperation2(NULL);_this->Hook1(NULL);_this->RequiredOperation2(NULL);_this->BaseOperation3(NULL);_this->Hook2(NULL);
}void Hook1(void* p) {}void Hook2(void* p) {}void RequiredOperations1(void*){};void RequiredOperation2(void*){};
void BaseOperation1(void* p) {std::cout << "AbstractClass says: I am doing the bulk of the work\n";
}
void BaseOperation2(void* p) {std::cout << "AbstractClass says: But I let subclasses override some operations\n";
}
void BaseOperation3(void* p) {std::cout << "AbstractClass says: But I am doing the bulk of the work anyway\n";
}void AbstractClass_Init(AbstractClass* _this)
{_this->RequiredOperation2 = RequiredOperation2;_this->RequiredOperations1 = RequiredOperations1;_this->BaseOperation1 = BaseOperation1;_this->BaseOperation2 = BaseOperation2;_this->BaseOperation3 = BaseOperation3;_this->Hook1 = Hook1;_this->Hook2 = Hook2;
}typedef struct
{AbstractClass _base;
}ConcreteClass1;void ConcreteClass1_RequiredOperations1(void* p){std::cout << "ConcreteClass1 says: Implemented Operation1\n";
}
void ConcreteClass1_RequiredOperation2(void* p) {std::cout << "ConcreteClass1 says: Implemented Operation2\n";
}void ConcreteClass1_Init(ConcreteClass1*p)
{AbstractClass_Init(&p->_base);p->_base.RequiredOperations1 = ConcreteClass1_RequiredOperations1;p->_base.RequiredOperation2 = ConcreteClass1_RequiredOperation2;
}typedef struct
{AbstractClass _base;
}ConcreteClass2;void ConcreteClass2_RequiredOperations1(void* p) {std::cout << "ConcreteClass2 says: Implemented Operation1\n";
}
void ConcreteClass2_RequiredOperation2(void* p)  {std::cout << "ConcreteClass2 says: Implemented Operation2\n";
}
void ConcreteClass2_Hook1(void* p) {std::cout << "ConcreteClass2 says: Overridden Hook1\n";
}void ConcreteClass2_Init(ConcreteClass2* p)
{AbstractClass_Init(&p->_base);p->_base.RequiredOperations1 = ConcreteClass2_RequiredOperations1;p->_base.RequiredOperation2 = ConcreteClass2_RequiredOperation2;p->_base.Hook1 = ConcreteClass2_Hook1;
}static void ClientCode(AbstractClass* class_) {// ...TemplateMethod(class_);// ...
}void TemplateMethodC()
{std::cout << "Same client code can work with different subclasses:\n";ConcreteClass1 c1;ConcreteClass1_Init(&c1);ClientCode(&c1._base);std::cout << "\n";std::cout << "Same client code can work with different subclasses:\n";ConcreteClass2 c2;ConcreteClass2_Init(&c2);ClientCode(&c2._base);
}

运行效果

访问者模式

访问者模式的介绍: https://refactoringguru.cn/design-patterns/visitor/cpp/example
访问者模式的C++实现: https://refactoringguru.cn/design-patterns/visitor/cpp/example
网页上说这个设计模式用的很少,他写的那个介绍,我没大看懂
我觉得这个老哥【idiot5lie】写的关于此设计模式的描述很好
【C++】设计模式全解析——访问者模式(code c++)

换成C语言写


#include <stdio.h>
#include <string>
#include <iostream>
#include <algorithm>
#include <array>struct ConcreteComponentA;
struct ConcreteComponentB;typedef struct
{void (* VisitConcreteComponentA)(ConcreteComponentA* element);void (* VisitConcreteComponentB)(ConcreteComponentB* element);
}Visitor;typedef struct
{void (*Accept)(void *,Visitor* visitor);
}Component;typedef struct ConcreteComponentA
{Component _base;std::string(*ExclusiveMethod)(ConcreteComponentA* p);
}ConcreteComponentA;
void ConcreteComponentA_Accept(void* p, Visitor* visitor);
std::string ExclusiveMethodOfConcreteComponentA(ConcreteComponentA* p);
void ConcreteComponentA_Init(ConcreteComponentA* p)
{p->_base.Accept = ConcreteComponentA_Accept;p->ExclusiveMethod = ExclusiveMethodOfConcreteComponentA;
}
void ConcreteComponentA_Accept(void* p, Visitor* visitor)
{ConcreteComponentA* pp = (ConcreteComponentA*)p;visitor->VisitConcreteComponentA(pp);
}std::string ExclusiveMethodOfConcreteComponentA(ConcreteComponentA* p) {return "A";
}typedef struct ConcreteComponentB
{Component _base;std::string(*ExclusiveMethod)(ConcreteComponentB* p);
}ConcreteComponentB;
void ConcreteComponentB_Accept(void* p, Visitor* visitor);
std::string ExclusiveMethodOfConcreteComponentB(ConcreteComponentB* p);
void ConcreteComponentB_Init(ConcreteComponentB* p)
{p->_base.Accept = ConcreteComponentB_Accept;p->ExclusiveMethod = ExclusiveMethodOfConcreteComponentB;
}void ConcreteComponentB_Accept(void* p, Visitor* visitor)
{ConcreteComponentB* pp = (ConcreteComponentB*)p;visitor->VisitConcreteComponentB(pp);
}std::string ExclusiveMethodOfConcreteComponentB(ConcreteComponentB* p) {return "B";
}typedef struct
{Visitor _base;
}ConcreteVisitor1;
void Visitor1_VisitConcreteComponentA(ConcreteComponentA* element);
void Visitor1_VisitConcreteComponentB(ConcreteComponentB* element);
void ConcreteVisitor1_Init(ConcreteVisitor1 *p)
{p->_base.VisitConcreteComponentA = Visitor1_VisitConcreteComponentA;p->_base.VisitConcreteComponentB = Visitor1_VisitConcreteComponentB;
}void Visitor1_VisitConcreteComponentA(ConcreteComponentA* element)
{std::cout << element->ExclusiveMethod(element) << " + ConcreteVisitor1\n";
}void Visitor1_VisitConcreteComponentB(ConcreteComponentB* element)
{std::cout << element->ExclusiveMethod(element) << " + ConcreteVisitor1\n";
}typedef struct
{Visitor _base;
}ConcreteVisitor2;void Visitor2_VisitConcreteComponentA(ConcreteComponentA* element);
void Visitor2_VisitConcreteComponentB(ConcreteComponentB* element);
void ConcreteVisitor2_Init(ConcreteVisitor2* p)
{p->_base.VisitConcreteComponentA = Visitor2_VisitConcreteComponentA;p->_base.VisitConcreteComponentB = Visitor2_VisitConcreteComponentB;
}
void Visitor2_VisitConcreteComponentA(ConcreteComponentA* element)
{std::cout << element->ExclusiveMethod(element) << " + ConcreteVisitor2\n";
}void Visitor2_VisitConcreteComponentB(ConcreteComponentB* element)
{std::cout << element->ExclusiveMethod(element) << " + ConcreteVisitor2\n";
}static void ClientCode(std::array<Component*, 2> components, Visitor* visitor) {// ...for (Component* comp : components) {comp->Accept(comp,visitor);}// ...
}void VisitorC()
{ConcreteComponentA a;ConcreteComponentA_Init(&a);ConcreteComponentB b;ConcreteComponentB_Init(&b);ConcreteVisitor1 v1;ConcreteVisitor1_Init(&v1);ConcreteVisitor2 v2;ConcreteVisitor2_Init(&v2);std::cout << "The client code works with all visitors via the base Visitor interface:\n";std::array<Component*, 2> components = { &a._base,&b._base };ClientCode(components, &v1._base);std::cout << "\n";std::cout << "It allows the same client code to work with different types of visitors:\n";ClientCode(components, &v2._base);
}

运行结果

END,完结撒花

【设计模式】我对设计模式的C语言解读(下)相关推荐

  1. 【设计模式】我对设计模式的C语言解读(上)

    这个文章的目的 我很早就知道有一个可以学设计模式的网站 一个乌克兰老哥搞得学设计模式的网站,还有爱好者直接翻译成中文的页面~ 我一直没能有机会学一学~ 每一种设计模式都有一个很生动的图解,还有对应的代 ...

  2. java语言描述一个行为_设计模式之责任链模式——Java语言描述

    责任链模式为请求创建了一个接受者对象的链.这种模式给予请求的类型,对请求的发送者和接受者进行解耦.这种类型的设计模式属于行为模式.在这种模式下,通常每个接收者都包含对另一个接收者的引用.如果一个对象不 ...

  3. java 设计模式 示例_Java设计模式–示例教程

    java 设计模式 示例 Design Patterns are very popular among software developers. A design pattern is a well- ...

  4. 备战面试日记(3.3) - (设计模式.23种设计模式之结构型模式)

    本人本科毕业,21届毕业生,一年工作经验,简历专业技能如下,现根据简历,并根据所学知识复习准备面试. 记录日期:2022.1.9 大部分知识点只做大致介绍,具体内容根据推荐博文链接进行详细复习. 文章 ...

  5. 备战面试日记(3.2) - (设计模式.23种设计模式之创建型模式)

    本人本科毕业,21届毕业生,一年工作经验,简历专业技能如下,现根据简历,并根据所学知识复习准备面试. 记录日期:2022.1.6 大部分知识点只做大致介绍,具体内容根据推荐博文链接进行详细复习. 文章 ...

  6. java设计模式:23种设计模式及其源代码演示实现

    java23种设计模式及其源代码演示实现 博主在CSDN已有三年,之前一直在看贴,受益颇多,不可多得的一个良好的学习平台,这一次,博主给大家分享一份传说中的java设计模式,源代码与其实现全部都有,希 ...

  7. Python、设计原则和设计模式-创建类设计模式

    Python.设计原则和设计模式 前言 程序的目标:高内聚 低耦合 有哪些设计原则 设计原则是「高内聚.低耦合」的具体落地. 单一职责原则要求在软件系统开发.设计中,一个类只负责一个功能领域的相关职责 ...

  8. 备战面试日记(3.4) - (设计模式.23种设计模式之行为型模式)

    本人本科毕业,21届毕业生,一年工作经验,简历专业技能如下,现根据简历,并根据所学知识复习准备面试. 记录日期:2022.1.12 大部分知识点只做大致介绍,具体内容根据推荐博文链接进行详细复习. 文 ...

  9. 23种设计模式——结构型设计模式(7种)

    目录 ☞ 23 种设计模式--创建型设计模式(5种) ☞ 23 种设计模式--结构型设计模式(7种) ☞ 23 种设计模式--行为型设计模式(11种) 3. 结构型设计模式 结构型模式描述如何将类或对 ...

最新文章

  1. JAVA连接数据库使用的API是什么呢,如何使用JDBC API在Java中建立数据库连接?
  2. Citrix XenDesktop 7.X 视频播放优化
  3. 对java面试文章的技术漫谈的C#技术理解
  4. 【控制】《多智能体系统一致性协同演化控制理论与技术》纪良浩老师-第12章-离散时间多智能体系统牵制一致性
  5. php性能优化二(PHP配置php.ini)
  6. excel怎么把单元格内某个字标红,其他字不变
  7. 使用 CNF 测试套件测试云原生最佳实践
  8. 第三十八期:用Git帮助写作者更好地完成工作
  9. R语言:ggplot2精细化绘图——以实用商业化图表绘图为例(转)
  10. Hadoop集群启动时NameNode未启动解决方法
  11. 有个做微商的兄弟,他是卖品牌运动鞋的,最近很苦恼
  12. Jmeter接口测试实例图文示例
  13. Android的ArrayAdapter、SimpleAdapter、BaseAdapter与ListView的使用
  14. VirtualBox 6.1.4的共享剪贴板确实有问题,6.1.0正常
  15. Javascript对象数组排序
  16. 基于 Roslyn 实现代码动态编译
  17. 钟平老师的逻辑英语语法
  18. 传奇源码分析-服务器端
  19. 2021年7月国产数据库排行榜:openGauss高歌猛进,GBase丢失第五
  20. 关于学校邮箱收不到matlab验证短信

热门文章

  1. uniapp自定义tabbar必看
  2. 2021-08-22 愿景和范围文档模板样例
  3. Glade+GTK+ 实现通讯录信息管理系统图形界面软件开发
  4. android沉浸状态栏和顶部状态栏背景色的设置
  5. Python 从 pyc 中获取编译 pyc 的 python 版本
  6. 香港科大EMBA校友黄立伟冠名两位商学院教授
  7. 中国制造2025新机遇 机器视觉行业爆发
  8. mysql查找 提速_MySQL加速查询速度的独门武器:查询缓存
  9. python入门笔记(1)
  10. 北邮计算机专业的培养方案,现代邮政学院2016级专业培养方案-北京邮电大学.PDF...