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

概述:

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

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;
}
发布了134 篇原创文章 · 获赞 20 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/u011583798/article/details/102237393