研磨设计模式之《模板方法模式template method》

mac2022-07-05  10

概述:

模板方法本质是将既定不变的步骤,流程,方法,算法封装起来对外提供统一的接口,以复用这些流程或算法步骤;我们以登录界面为例,假设有两种用户普通用户client和管理员用户master,他们都需要登录login,即包含获取用户信息find_get_user,密码加密encrypt_pwd,匹配获得结果match这几步,只是具体的实现可能不同。我们将登录步骤抽象为统一的模板,封装为login方法,实现过程复用。

1. login_template抽象类定义,实现:

//定义 #ifndef _LOGIN_TEMPLATE_H #define _LOGIN_TEMPLATE_H #include<stdbool.h> #include"login_model.h" struct login_template_vmt; struct login_template { const struct login_template_vmt* vptr; bool (*login)(struct login_template* pthis, struct login_model* plm); struct login_model* (*find_login_user)(struct login_template* pthis, int id); char* (*encrypt_pwd)(struct login_template* pthis, char* pwd); bool (*match)(struct login_template* pthis, struct login_model* plm, struct login_model* pdb); }; ///< 将具体实现可能不同的方法放入虚表 struct login_template_vmt { struct login_model* (*find_login_user_vm)(struct login_template* pthis, int id); char* (*encrypt_pwd_vm)(struct login_template* pthis, char* pwd); }; extern void login_template_init(struct login_template* pthis); #endif // _LOGIN_TEMPLATE_H //实现: #include<stdio.h> #include<stdlib.h> #include<stdbool.h> #include<string.h> #include"login_model.h" #include"login_template.h" ///< 模板方法 static bool login(struct login_template* pthis, struct login_model* plm) { ///< 第一步 struct login_model* dblm = pthis->find_login_user(pthis, plm->get_id(plm)); if (dblm != NULL) { ///< 第二步 char* crypwd = pthis->encrypt_pwd(pthis, plm->get_pwd(plm)); plm->set_pwd(plm, crypwd); ///< 第三步 return pthis->match(pthis, plm, dblm); } } ///< 不提供默认实现,必须由子类实现 static struct login_model* find_login_user(struct login_template* pthis, int id) { pthis->vptr->find_login_user_vm(pthis, id); ///< must realized by derived class } ///< 提供默认实现,可由子类覆盖 static char* encrypt_pwd(struct login_template* pthis, char* pwd) { if (pthis->vptr->encrypt_pwd_vm != NULL) { pthis->vptr->encrypt_pwd_vm(pthis, pwd); } else { printf("default plain text\n"); return pwd; ///< default realization } } static bool match(struct login_template* pthis, struct login_model* plm, struct login_model* pdb) { if (plm->get_id(plm) == pdb->get_id(pdb) && !strcmp(plm->get_pwd(plm), pdb->get_pwd(pdb))) { printf("login successfully!\n"); return true; } return false; } void login_template_init(struct login_template* pthis) { static const struct login_template_vmt vmt = { .find_login_user_vm = NULL, .encrypt_pwd_vm = NULL, }; pthis->vptr = &vmt; pthis->login = login; pthis->find_login_user = find_login_user; pthis->encrypt_pwd = encrypt_pwd; pthis->match = match; }

2. client_login子类定义,实现:

///< 定义 #ifndef _CLIENT_LOGIN_H #define _CLIENT_LOGIN_H #include<stdbool.h> #include"login_model.h" #include"login_template.h" struct client_login { struct login_template super; bool (*login)(struct login_template* pthis, struct login_model* plm); struct login_model* (*find_login_user)(struct login_template* pthis, int id); char* (*encrypt_pwd)(struct login_template* pthis, char* pwd); bool (*match)(struct login_template* pthis, struct login_model* plm, struct login_model* pdb); }; extern struct client_login* construct_client_login(void); extern void destruct_client_login(struct client_login* pthis); #endif // _CLIENT_LOGIN_H ///< 实现 #include<stdio.h> #include<stdlib.h> #include<string.h> #include"login_template.h" #include"login_model.h" #include"client_login.h" static struct login_model* find_login_user_ov(struct login_template* pthis, int id) { ///< 这里通过直接构造,来模拟查找 struct login_model* plm = construct_login_model(); plm->set_id(plm, id); plm->set_pwd(plm, "xxdk"); return plm; } static void client_login_init(struct client_login* pthis) { static const struct login_template_vmt vmt = { .find_login_user_vm = find_login_user_ov, ///< method override }; login_template_init(&pthis->super); pthis->super.vptr = &vmt; pthis->login = pthis->super.login; ///< use base class method pthis->match = pthis->super.match; ///< use base class method pthis->encrypt_pwd = pthis->super.encrypt_pwd; ///< use base class method } struct client_login* construct_client_login(void) { struct client_login* pthis = malloc(sizeof(*pthis)); memset(pthis, 0, sizeof(*pthis)); client_login_init(pthis); return pthis; } void destruct_client_login(struct client_login* pthis) { free(pthis); }

3. master_login子类定义,实现:

///< 定义 #ifndef _MASTER_LOGIN_H #define _MASTER_LOGIN_H #include<stdbool.h> #include"login_model.h" #include"login_template.h" struct master_login { struct login_template super; bool (*login)(struct login_template* pthis, struct login_model* plm); struct login_model* (*find_login_user)(struct login_template* pthis, int id); char* (*encrypt_pwd)(struct login_template* pthis, char* pwd); bool (*match)(struct login_template* pthis, struct login_model* plm, struct login_model* pdb); }; extern struct master_login* construct_master_login(void); extern void destruct_master_login(struct master_login* pthis); #endif // _MASTER_LOGIN_H ///< 实现 #include<stdio.h> #include<stdlib.h> #include<string.h> #include"login_template.h" #include"login_model.h" #include"master_login.h" static struct login_model* find_login_user_ov(struct login_template* pthis, int id) { struct login_model* plm = construct_login_model(); plm->set_id(plm, id); plm->set_pwd(plm, "xxdk"); return plm; } static char* encrypt_pwd_ov(struct login_template* pthis, char* pwd) { printf("master encrypt pwd\n"); return pwd; } static void master_login_init(struct master_login* pthis) { static const struct login_template_vmt vmt = { .find_login_user_vm = find_login_user_ov, ///< method override .encrypt_pwd_vm = encrypt_pwd_ov, ///< method override }; login_template_init(&pthis->super); pthis->super.vptr = &vmt; pthis->login = pthis->super.login; ///< use base class method pthis->match = pthis->super.match; ///< use base class method } struct master_login* construct_master_login(void) { struct master_login* pthis = malloc(sizeof(*pthis)); memset(pthis, 0, sizeof(*pthis)); master_login_init(pthis); return pthis; } void destruct_master_login(struct master_login* pthis) { free(pthis); }

4. 辅助的login_model类定义,实现, 用于封装用户信息:

///< 定义 #ifndef _LOGIN_TEMPLATE_H #define _LOGIN_TEMPLATE_H #include<stdbool.h> #include"login_model.h" struct login_template_vmt; struct login_template { const struct login_template_vmt* vptr; bool (*login)(struct login_template* pthis, struct login_model* plm); struct login_model* (*find_login_user)(struct login_template* pthis, int id); char* (*encrypt_pwd)(struct login_template* pthis, char* pwd); bool (*match)(struct login_template* pthis, struct login_model* plm, struct login_model* pdb); }; struct login_template_vmt { struct login_model* (*find_login_user_vm)(struct login_template* pthis, int id); char* (*encrypt_pwd_vm)(struct login_template* pthis, char* pwd); }; extern struct login_template* construct_login_template(void); extern void login_template_init(struct login_template* pthis); extern void desturct_login_template(struct login_template* pthis); #endif // _LOGIN_TEMPLATE_H ///< 实现 #include<stdio.h> #include<stdlib.h> #include<string.h> #include"login_model.h" static int get_id(struct login_model* pthis) { return pthis->id; } static void set_id(struct login_model* pthis, int id) { pthis->id = id; } static char* get_pwd(struct login_model* pthis) { return pthis->pwd; } static void set_pwd(struct login_model* pthis, char* pwd) { strncpy(pthis->pwd, pwd, 16); } static void login_model_init(struct login_model* pthis) { pthis->get_id = get_id; pthis->set_id = set_id; pthis->get_pwd = get_pwd; pthis->set_pwd = set_pwd; } struct login_model* construct_login_model(void) { struct login_model* pthis = malloc(sizeof(*pthis)); login_model_init(pthis); return pthis; } void destruct_login_model(struct login_model* pthis) { free(pthis); }

5. 测试文件:

#include<stdio.h> #include<stdbool.h> #include"login_template.h" #include"login_model.h" #include"client_login.h" #include"master_login.h" int main() { struct login_model* usr; struct login_template* plt; usr = construct_login_model(); usr->set_id(usr, 1); usr->set_pwd(usr, "xxdk"); printf("client user login: \n"); plt = (struct login_template*)construct_client_login(); plt->login(plt, usr); destruct_client_login((struct client_login*)plt); printf("master user login: \n"); plt = (struct login_template*)construct_master_login(); plt->login(plt, usr); destruct_master_login((struct master_login*)plt); destruct_login_model(usr); return 0; }
最新回复(0)