IOS 设计模式 桥接模式(bridge)

本文介绍了桥接模式的概念及其应用场景,并通过电视机与遥控器的例子详细解释了桥接模式的实现方式。文章展示了如何通过桥接模式将抽象部分与实现部分分离,以达到两者独立变化的目的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载:http://www.sxt.cn/info-6567-u-10434.html

何为桥接模式?

桥接模式的目的是把抽象层次结构从其实现中分离出来,使其能够独立变更。抽象层定义了供客户端使用的上层的抽象接口。实现层定义了供抽象层使用的底层接口。实现类的引用被封装于抽象层的实例中,桥接就形成。(与外观模式有一定的相似之处)。

桥接模式:将抽象部分与它的实现部分分离,使它们都可以独立地变化。

何时使用桥接模式?

@:不想在抽象与其实现之间形成固定的绑定关系,这样就能在运行时切换实现。

@:抽象及其实现都应可以通过子类化独立进行扩展。

@:对抽象的实现进行修改不应影响客户端代码。

@:如果每个实现需要额外的子类以细化抽象,则说明有必要把它们分成两个部分。

@:想在带有不同抽象接口的多个对象之间共享一个实现。

桥接模式的实例应用

比如有一家电视机制造商,他们生产的每台电视都带一个遥控器,用户可以用遥控器进行频道切换之类的操作。在这里遥控器是控制电视机的接口,如果每个电视机型号需要一个专用的遥控器,那么单是遥控器就会导致设计激增。不过,每个遥控器都有些功能是各种型号电视机共有的,比如切换频道、调节音量和电源开关。而且每台电视机都应该能够通过基本命令接口,响应遥控器发来的这些命令。我们可以把遥控器逻辑同实际的电视机型号分离开来。这样电视机型号的改变就不会对遥控器的设计有任何的影响。遥控器的同一个设计可以被复用和扩展,而不会影响其他电视机型号。如下图所示:


AbstractRemoteControl是定义了供客户端使用的上层接口的父接口。它有一个对TVProtocol视力的引用,TVProtocol定义了实现类的接口。这个接口不必跟AbstractRemoteControl的接口一致,其实两个接口可以完全不同。TVProtocol的接口提供基本的操作,而AbstractRemoteControl的上层操作基于这些基本操作。当客户端向AbstractRemoteControl的实例发送operation消息时,这个方法向imp发送operationImp消息,底下的实际由TVA或TVB将作出响应并接受任务。

因此想要往系统中添加新的TVProtocol时,所要做的只是为TVProtocol创建一个新的实现类,响应operationImp消息并在其中执行任何具体的操作。不过,这对AbstractRemoteControl方面不会有任何影响。同样,如果想修改AbstractRemoteControl的接口或者创建更细化的AbstractRemoteControl类,也不会影响桥接的另一头。

来看下具体的代码实现,先看下抽象部分的代码实现,AbstractRemoteControl代码如下:

1
2
3
4
5
6
7
8
9
#import<Foundation/Foundation.h>
#import"TVProtocol.h"
@interfaceAbstractRemoteControl:NSObject
@property(nonatomic,weak)id<TVProtocol>tvProtocol;
-( void )detectTVFunction;
@end
1
2
3
4
5
6
7
8
9
#import"AbstractRemoteControl.h"
@implementationAbstractRemoteControl
-( void )detectTVFunction{
NSLog(@ "检测电视机具备的功能,由子类来进行实现" );
}
@end

在AbstractRemoteControl类中保持了对TVProtocol实例对象的引用,定义了供客户端使用的上层抽象接口detectTVFunction,而这个方法的具体实现则由其子类去实现,ConcreteRemoteControl代码如下:

1
2
3
4
5
6
7
8
#import"AbstractRemoteControl.h"
@interfaceConcreteRemoteControl:AbstractRemoteControl
//重写该方法
-( void )detectTVFunction;
@end
1
2
3
4
5
6
7
8
9
10
11
#import"ConcreteRemoteControl.h"
@implementationConcreteRemoteControl
-( void )detectTVFunction{
[self.tvProtocolswitchChannel];
[self.tvProtocoladjustVolume];
[self.tvProtocolpowerSwitch];
}
@end

从这里我们可以看出,当客户端向ConcreteRemoteControl的实例发送detectTVFunction消息时,这个方法向TVProtocol发送switchChannel、adjustVolume、powerSwitch三个消息,TVA或TVB将作出响应并接受任务。至此,抽象部分代码已经完成了,接着看下实现部分的代码,TVProtocol代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
#import<Foundation/Foundation.h>
@protocolTVProtocol<NSObject>
@required
-( void )switchChannel; //切换频道
-( void )adjustVolume; //调节音量
-( void )powerSwitch; //电源开关
@end

这就是一个协议,协议里面定义了三个方法,以后在创建电视机实例的时候,就必须遵守该协议,从而保证了电视机具有相同的功能。AbstractTV的代码如下:

1
2
3
4
5
#import<Foundation/Foundation.h>
#import"TVProtocol.h"
@interfaceAbstractTV:NSObject<TVProtocol>
@end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#import"AbstractTV.h"
@implementationAbstractTV
-( void )switchChannel{
NSLog(@ "切换频道,由具体的子类来实现" );
}
-( void )adjustVolume{
NSLog(@ "调节音量,由具体的子类来实现" );
}
-( void )powerSwitch{
NSLog(@ "电源开关,由具体的子类来实现" );
}
@end

TVA的代码如下:

1
2
3
4
5
6
7
8
9
10
#import"AbstractTV.h"
@interfaceTVA:AbstractTV
//重写这三个方法
-( void )switchChannel;
-( void )adjustVolume;
-( void )powerSwitch;
@end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#import"TVA.h"
@implementationTVA
-( void )switchChannel{
NSLog(@ "电视机A具备了切换频道的功能" );
}
-( void )adjustVolume{
NSLog(@ "电视机A具备了调节音量的功能" );
}
-( void )powerSwitch{
NSLog(@ "电视机A具备了电源开关的功能" );
}
@end

TVB的代码如下:

1
2
3
4
5
6
7
8
9
10
#import"AbstractTV.h"
@interfaceTVB:AbstractTV
//重写这三个方法
-( void )switchChannel;
-( void )adjustVolume;
-( void )powerSwitch;
@end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#import"TVB.h"
@implementationTVB
-( void )switchChannel{
NSLog(@ "电视机B具备了切换频道的功能" );
}
-( void )adjustVolume{
NSLog(@ "电视机B具备了调节音量的功能" );
}
-( void )powerSwitch{
NSLog(@ "电视机B具备了电源开关的功能" );
}
@end

到这里,桥接模式代码已经完成了,在客户端该怎么去应用呢?我们通过下面的客户端代码来说明,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#import"ViewController.h"
#import"AbstractRemoteControl.h"
#import"ConcreteRemoteControl.h"
#import"TVProtocol.h"
#import"AbstractTV.h"
#import"TVA.h"
#import"TVB.h"
typedef id<TVProtocol>TVProtocol; //在这里要进行一下转换声明,否则类中不能识别TVProtocol.
@interfaceViewController()
@end
@implementationViewController
-( void )viewDidLoad{
[superviewDidLoad];
AbstractRemoteControl*remoteControl=[[ConcreteRemoteControlalloc]init];
TVProtocoltvProtocol=[[TVAalloc]init];
remoteControl.tvProtocol=tvProtocol;
[remoteControldetectTVFunction];
NSLog(@ "///////////////////////////////" );
tvProtocol=[[TVBalloc]init];
remoteControl.tvProtocol=tvProtocol;
[remoteControldetectTVFunction];
/**
*桥接模式:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
*在本例中,AbstractRemoteControl是抽象部分,TVProtocol是其实现部分。
*/
}
-( void )didReceiveMemoryWarning{
[superdidReceiveMemoryWarning];
//Disposeofanyresourcesthatcanberecreated.
}
@end

日志输出如下:

1
2
3
4
5
6
7
2015-09-0122:59:06.295Bridge[16464:703747]电视机A具备了切换频道的功能
2015-09-0122:59:06.295Bridge[16464:703747]电视机A具备了调节音量的功能
2015-09-0122:59:06.296Bridge[16464:703747]电视机A具备了电源开关的功能
2015-09-0122:59:06.296Bridge[16464:703747] ///////////////////////////////
2015-09-0122:59:06.296Bridge[16464:703747]电视机B具备了切换频道的功能
2015-09-0122:59:06.296Bridge[16464:703747]电视机B具备了调节音量的功能
2015-09-0122:59:06.296Bridge[16464:703747]电视机B具备了电源开关的功能

通过桥接模式的应用,我们可以把抽象部分与实现部分分离,使它们都可以独立的变化。比如在本例中,对AbstractRemoteControl的修改,不会影响到TVProtocol。同样对TVProtocol的修改,也不会影响AbstractRemoteControl。这正是桥接模式带给我们的便利性。

demo链接地址:https://github.com/guoshimeihua/Bridge


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值