C语言实现设计模式,往期回顾:
/ 一、简介 /
1.代理模式,是构造型的设计模式之一,是一个使用率比较高的模式,它可以为其他对象提供一种代理(Proxy)以控制对这个对象的访问。
2.所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代理与被代理的目标类交互,而代理一般在交互的过程中(交互前后),进行某些特别的处理。
3.代理模式也叫做委托模式,在日常的应用中,代理模式可以提供非常好的访问控制。
4.代理模式的优点: 职责清晰、高扩展性。
5.代理模式的类图如下,我们作为client使用时,直接访问interface这个抽象接口,真实的RealSubject与Proxy代理类继承该interface抽象接口,并实现接口定义函数。
/ 二、设计实现 /
1.设计思路,本设计以服装店卖衣服为例,通过服装店自己卖衣服和淘宝店代理卖衣服对比,感受一下代理模式优点。
2.设计的抽象接口如下。
//定义的代理模式抽象接口
typedef struct IProxy_t
{
void (*sale)(void *obj); //卖衣服接口
void (*discount)(void *obj, float discount_num); //打折接口
void (*free)(void *obj); //最后释放内存
}IProxy_t;
3.服装店相关定义的实现
//服装店结构体
//注: 前面三个函数接口顺序与IProxy_t定义的要一致。
typedef struct ClotheStore_t
{
void (*sale)(void *obj); //卖衣服函数
void (*discount)(void *obj, float discount_num);//打折函数
void (*free)(void *obj); //释放内存
float price; //服装价格
}ClotheStore_t;
/**
* 简介:实现释放内存接口
* 参数:传入当前的服装店结构体
* 返回值:无
*/
static void clothe_store_free(void *obj)
{
ClotheStore_t *csobj = (ClotheStore_t*)obj;
if(csobj) free(csobj);
}
/**
* 简介:实现卖衣服函数接口
* 参数:传入当前的服装店结构体
* 返回值:无
*/
static void clothe_store_sale(void *obj)
{
ClotheStore_t *csobj = (ClotheStore_t*)obj;
printf("服装店: 卖衣服! 价格是: %.2f元\n", ((ClotheStore_t*)obj)->price);
}
/**
* 简介:实现打折计算函数接口
* 参数:传入当前的服装店结构体、 打折值
* 返回值:无
*/
static void clothe_store_discount(void *obj, float discount_num)
{
printf("服装店: 现在做活动打 %.1f 折, 欢迎选购! \n", discount_num);
ClotheStore_t *cs = (ClotheStore_t*)obj;
cs->price *= discount_num/10.0;
}
/**
* 简介:服装店结构体构造函数
* 参数:无
* 返回值:创建的服装店对象
*/
ClotheStore_t* constructor_clothe_store(void)
{
ClotheStore_t* obj = (ClotheStore_t*)malloc(sizeof(ClotheStore_t)); //申请内存
obj->price = 588; //数据成员赋值
obj->discount = clothe_store_discount; //函数指针赋值,便于后续调用,下同
obj->sale = clothe_store_sale;
obj->free = clothe_store_free;
return obj;
}
4.淘宝代理接口定义及实现如下。
//定义淘宝代理结构体
//注:前3个函数指针与IProxy_t定义一致,方便后续发生“多态”作用
//即动态选择函数执行
typedef struct ProxyTaoBao_t
{
void (*sale)(void *obj); //淘宝卖衣服
void (*discount)(void *obj, float discount_num);//打折
void (*free)(void *obj); //释放资源
void (*before)(void *obj); //售前
void (*after)(void *obj); //售后
ClotheStore_t *csobj; //给服装店做代理
}ProxyTaoBao_t;
/**
* 简介: 实现淘宝代理卖衣服函数接口
* 参数:传入当前调用的结构体
* 返回值: 无
* 其他: 代理服装店卖衣服,实际上真正卖衣服还是服务站
* 不过由淘宝代理,增加一些售前、售后服务等
*/
static void taobao_sale(void *obj)
{
ProxyTaoBao_t *tbobj = (ProxyTaoBao_t*)obj;
tbobj->before(tbobj); //做售前工作
tbobj->discount(tbobj, 9.5); //淘宝做活动打折9.5折
tbobj->csobj->discount(tbobj->csobj, 9.8); //商家打折9.8折
tbobj->csobj->sale(tbobj->csobj); //实际卖衣服还是服装商家
tbobj->after(tbobj); //做售后工作
}
/**
* 简介: 实现淘宝代理打折函数接口
* 参数:传入当前调用的结构体、打折值
* 返回值: 无
*/
static void taobao_discount(void *obj, float discount_num)
{
ProxyTaoBao_t *tbobj = (ProxyTaoBao_t*)obj;
tbobj->csobj->price *= discount_num/10.0;
printf("淘宝做活动, 全场打 %.1f 折! 欢迎选购!!!\n", discount_num);
}
/**
* 简介: 实现淘宝代理售前函数接口
* 参数:传入当前调用的结构体
* 返回值: 无
*/
static void taobao_before(void *obj)
{
printf("淘宝售前: 亲!欢迎咨询...\n");
}
/**
* 简介: 实现淘宝代理售后函数接口
* 参数:传入当前调用的结构体
* 返回值: 无
*/
static void taobao_after(void *obj)
{
printf("淘宝售后: 亲!有问题请联系我哦...\n");
}
/**
* 简介: 实现淘宝代理free函数接口
* 参数:传入当前调用的结构体
* 返回值: 无
*/
static void taobao_free(void *obj)
{
ProxyTaoBao_t* tbobj = (ProxyTaoBao_t*)obj;
if(tbobj->csobj) free(tbobj->csobj);
if(tbobj) free(tbobj); //释放资源
}
/**
* 简介: 淘宝代理构造函数,申请对象资源,初始化等
* 参数:无
* 返回值: 淘宝代理对象结构体指针
*/
ProxyTaoBao_t* constructor_proxy_taobao(void)
{
ProxyTaoBao_t* obj = (ProxyTaoBao_t*)malloc(sizeof(ProxyTaoBao_t));//申请内存
obj->after = taobao_after; //赋值函数指针,便于后续指针调用
obj->before = taobao_before; //赋值函数指针,便于后续指针调用,下同
obj->csobj = constructor_clothe_store(); //创建实体店对象
obj->discount = taobao_discount;
obj->free = taobao_free;
obj->sale = taobao_sale;
return obj;
}
/ 三、测试 /
我们来测试对比一下服装店直接卖衣服和淘宝店代理卖衣服的区别,测试程序如下:
int main(void)
{
IProxy_t *obj = NULL;
printf("------------------------------\n");
printf("普通实体店卖衣服:\n");
ClotheStore_t *csobj = constructor_clothe_store();
obj = (IProxy_t*)csobj;
obj->discount(obj, 9.8);
obj->sale(obj);
obj->free(obj);
printf("\n------------------------------\n");
printf("淘宝代理卖衣服: \n");
ProxyTaoBao_t *tbobj = constructor_proxy_taobao();
obj = (IProxy_t*)tbobj;
obj->sale(obj);
obj->free(obj);
return 0;
}
测试结果:
/ 四、总结 /
1.通过上面的测试结果,我们可以了解到,真正干活的还是服装店,不过加上代理模式后,整个销售流程更加完善,功能更加丰富。实际开放中,代理模式可以较小程度的修改原有程序来实现增加新的功能。
2.虽然C语言是面向过程的编程语言,但是我们在设计程序的时候,可以考虑用面向对象的方式去设计,这样提高我们程序的“高内聚、低耦合”特性,便于维护。
想要整个工程文件的小伙伴:在微信公众号【Linux编程用C】后台回复 【designer】 即可获取,不断更新中!
欢迎大家加小C微信【LinuxCodeUseC】,我们一起交流讨论学习!
PS:若大家想看C语言版本的其他设计模式,
请大家 点赞! 转发!关注吧!~~