类对象结构型模式之:Bridge(桥接模式)-- C语言例子


前言

        软软件设计模式(Design pattern),简称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。--来自百度百科。
        既然设计模式有那么多好处,我们在做程序设计的时候,就应该充分考虑自己需要解决的问题是否有一个设计模式与之相似,尽量使用现有的解决方案来设计程序,避免代码重复或自己考虑不足导致设计缺陷。
        本周五参加了设计模式研讨会,讨论的主题就是桥接模式(bridge),这篇博文的目的是对桥接模式的总结,以及分享一个桥接模式的C语言应用例子,希望对想学习这个模式的同学有所帮助。

一、桥接模式总结

1、模式意图

将抽象部分和实现部分分离,使他们可以独立地变化。

2、参与者

Abstraction
--定义抽象类的接口,维护一个指向Implementor类型对象的指针。
RefinedAbstraction
-- 扩充Abstraction定义的接口。
Implementor
-- 定义实现类的接口,该接口不一定要和Abstraction的接口完全一致,Implementor接口仅提供基本操作,Abstraction则定义了基于这些操作的比较高层次的操作。
ConcreteImplementor
-- 实现Implementor接口。

3、结构及效果

结构图:

在这里插入图片描述

效果:
1、分离接口及其实现部分。
2、提高可扩展性。
3、实现细节对客户透明。

4、适用性

1、你不希望在抽象和它的实现之间有一个固定的绑定关系。
2、类的抽象及实现都应该可以通过生成子类来扩展功能。
3、对一个抽象的实现部分的修改不应该影响客户。
4、对客户隐藏实现细节。
5、多个对象共享实现,但客户并不知道这一点。

二、桥接模式C语言用例

1、用例背景描述

         在跨平台应用程序,代码一般是通过宏定义来条件编译,区分不同平台的代码。但是,使用宏定义的方式,只能用于代码量较小的程序,如果程序代码量特别大, 或者系统平台比较多,使用宏定义的方式来区分不同平台的代码,将会使代码的可读性变得非常差,也不利于代码维护。而使用桥接模式,定义的接口可以在不同平台上共享而无需修改,每个平台只需提供一个本平台的一个具体实现即可。这样的方式,接口和实现分离,接口和实现两个部分可以独立变化,互不干扰。
        下边举的一个例子是桥接模式在网络接口设计中的应用,接口定义各平台统一的接口if_info_t,具体平台实现if_info_impl_t实现接口。这样if_info_t在客户代码中应用,移植不同平台时,不需要修改代码。而每个具体平台实现if_info_impl_t,实现网络接口功能,同时也可以扩展本平台其他的功能,可以独立变化而不影响接口。

2、用例结构图

在这里插入图片描述

if_info_t :定义统一的网络接口,桥接模式中的Abstraction;
if_info_impl_t:具体平台的接口,桥接模式中的Implementor;
if_info_linux_impl_t:Linux平台网络接口实现类,桥接模式中的ConcreteImplementor;
if_info_linux_impl_t:Windows平台网络接口实现类,桥接模式中的ConcreteImplementor;

3、C语言代码实现

为了代码使代码简洁,这里成员函数只贴一个get_ip即可,只要整体代码结构体现出桥接模式的即可。
1、if_info_t 定义及实现:
         该类定义统一的网络接口,必须获取网络设备的IP地址:get_ip。在对象创建函数if_info_create内部,通过创建一个抽象工厂对象,由工厂负责获取具体平台的if_info_impl_t对象。一般工厂只有一个,if_info_factory_create内部实现应该是单例。客户使用这个类,并不会涉及具体的实现类的任何细节,移植到不同平台,客户代码是不需要改变的。在工厂当中,根据特定的平台,产生该平台的实现类对象即可。
//.h
typedef struct _if_info_t if_info_t;
typedef char* (*get_ip_t)(const char* interface_name);

/**
 * @class if_info_t 
 * 网卡接口。
 */
struct _if_info_t {
  if_info_impl_t* impl;
  char* interface_name;
  int8_t type;
};

if_info_t* if_info_create(const char* interface_name, int8_t type);
char* get_ip(if_info_t* interface);


//.c
char* get_ip(if_info_t* interface) {
	return  interface->impl->get_ip(interface->interface_name);
}

if_info_t* if_info_create(const char* interface_name, int8_t type) {
	if_info_t* if_info = TKMEM_ZALLOC(if_info_t);
	if_info_impl_t* impl = if_info_factory_create()->get_if_info();
	if_info->impl = impl;
	if_info->interface_name = tk_strdup(interface_name);;
	if_info->type = type;
	return if_info ;
}

2、if_info_impl_t 定义:
定义实现类的统一接口。

//.h

/**
 * @class if_info_impl_t 
 * 网卡实现接口。
 */
struct if_info_impl_t {
  get_ip_t get_ip;
};
}

3、if_info_linux_impl_t 定义及实现:
定义Linux平台的实现类。get_ip获取该平台的IP地址。if_info_linux_impl_create创建Linux平台实现类对象,这个函数可以供工厂使用。

//.h
/**
 * @class if_info_linux_impl_t 
 * 网卡接口--linux。
 */
struct if_info_linux_impl_t {
  if_info_impl_t parent;
};

//.c

char* get_ip(const char* interface_name) {
	return  get_ip_by_interface_name(interface_name);
}

if_info_impl_t* if_info_linux_impl_create(const char* interface_name, int8_t type) {
  if_info_linux_impl_t* linux_network_interface = TKMEM_ZALLOC(if_info_linux_impl_t);
  return_value_if_fail(linux_network_interface != NULL, NULL);
  if_info_impl_t* parent = (if_info_impl_t*)linux_network_interface;
  parent->get_ip = get_ip;
  return parent;
}


4、if_info_windows_impl_t 定义及实现:
定义Windows平台的实现类。get_ip获取该平台的IP地址。if_info_windows_impl_create创建Windows平台实现类对象,这个函数可以供工厂使用。

//.h
/**
 * @class if_info_windows_impl_t 
 * 网卡接口--linux。
 */
struct if_info_windows_impl_t {
  if_info_impl_t parent;
};

//.c

char* get_ip(const char* interface_name) {
	return  get_ip_by_interface_name(interface_name);
}

if_info_impl_t* if_info_windows_impl_create(const char* interface_name, int8_t type) {
  if_info_windows_impl_t* windows_network_interface = TKMEM_ZALLOC(if_info_windows_impl_t);
  return_value_if_fail(windows_network_interface != NULL, NULL);
  if_info_impl_t* parent = (if_info_impl_t*)windows_network_interface;
  parent->get_ip = get_ip;
  return parent;
}



总结

         桥接模式的思想是把接口定义和接口实现相分离,接口内部有一个抽象实现类的指针,接口的功能通过这个指针实现。具体实现类实现接口定义的功能。对于客户来说,他们只知道Abstraction对象及Implementor指针,对具体的类ConcreteImplementor一无所知。为了获取Implementor指针,引入了工厂对象,由工厂对象创建具体的ConcreteImplementor对象并返回。桥接模式思想是简单的,把接口和实现完全解耦合,接口和实现两个部分都可以独立扩展而不会相互影响,做到了程序设计的开闭原则。          这个模式的难点是Implementor指针赋值,客户代码是不应该知道ConcreteImplementor类的,想通过客户自己创建ConcreteImplementor对象,并把指针赋值给Implementor指针是不现实的,因为这样就会把接口定义和接口实现捆绑在一起,完全背离了桥接模式的意图。引入一个工厂对象,把它作为接口和实现之间的桥梁,客户代码就不需要知道ConcreteImplementor了,Implementor指针赋值交给工厂对象就能完美解决。工厂对象的设计可以参考[《AWTK工厂模式--符合开闭原则的工厂模式》](https://blog.csdn.net/woody218/article/details/112447126?spm=1001.2014.3001.5501)
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值