书接上回
由于内容太多,编辑器太卡了,所以分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(¤t_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();
}