桥梁模式属于结构类的设计模式,示意结构图如下:
桥梁模式所涉及的角色有:
● 抽象化(Abstraction)角色:抽象化给出的定义,并保存一个对实现化对象的引用。
● 修正抽象化(RefinedAbstraction)角色:扩展抽象化角色,改变和修正父类对抽象化的定义。
● 实现化(Implementor)角色:这个角色给出实现化角色的接口,但不给出具体的实现。必须指出的是,这个接口不一定和抽象化角色的接口定义相同,实际上,这两个接口可以非常不一样。实现化角色应当只给出底层操作,而抽象化角色应当只给出基于底层操作的更高一层的操作。
● 具体实现化(ConcreteImplementor)角色:这个角色给出实现化角色接口的具体实现。
关键点:
1、抽象化角色可以通过向不同的实现化对象委派达到动态转换自己的目的
2、抽象化角色和实现化角色之间是聚合关系,而不是继承关系
如果 一个类需要知道另一个类的属性和方法,可以选择继承,也可以选择组合(聚合),在使用组合时,则需要持有对方的引用
以一个万能遥控的例子说明该模式的应用:(为了在同一个文件共存,代码中类前面的public都省略了)
1 packagedesignpatterns.strucural;2
3 //抽象角色--Abstraction
4 abstract classAbstractRemoteControl {5
6 protectedITV tv;7
8 public voidbindImpl(ITV tv){9 this.tv =tv;10 }11
12 public voidturnOn(){13 tv.on();14 }15
16 public voidturnOff(){17 tv.off();18 }19
20 public void setChannel(intchannel){21 tv.switchChannel(channel);22 }23 }24 //精确抽象角色--RefinedAbstraction
25 class PcRemoteControl extendsAbstractRemoteControl {26
27 @Override28 public voidturnOn() {29 System.out.println("Pc On");30 }31 }32
33 class CommonRemoteControl extendsAbstractRemoteControl{34
35 @Override36 public voidturnOn() {37 super.turnOn();38 }39
40 @Override41 public voidturnOff() {42 super.turnOff();43 }44
45 @Override46 public void setChannel(intchannel) {47 super.setChannel(channel);48 }49 }50
51 //实现角色--mplementor
52 /*
53 * 首先定义电视机的接口:ITV*/
54 interfaceITV {55
56 public voidon();57 public voidoff();58 public void switchChannel(intchannel);59 }60 //具体实现角色--ConcreteImplementor1
61 /*
62 * 再实现三星的ITV接口。*/
63 class SamsungTV implementsITV {64 @Override65 public voidon() {66 System.out.println("Samsung is turned on.");67 }68
69 @Override70 public voidoff() {71 System.out.println("Samsung is turned off.");72 }73
74 @Override75 public void switchChannel(intchannel) {76 System.out.println("Samsung: channel - " +channel);77 }78 }79 //具体实现角色--ConcreteImplementor2
80 /*
81 * 再实现索尼的ITV接口。*/
82 class SonyTV implementsITV {83
84 @Override85 public voidon() {86 System.out.println("Sony is turned on.");87 }88
89 @Override90 public voidoff() {91 System.out.println("Sony is turned off.");92 }93
94 @Override95 public void switchChannel(intchannel) {96 System.out.println("Sony: channel - " +channel);97 }98 }99
100 //测试类
101 public classBridge {102 public static voidmain(String[] args){103 ITV tv1 = newSonyTV();104 ITV tv2 = newSamsungTV();105
106 AbstractRemoteControl control = newCommonRemoteControl();107 control.bindImpl(tv1);108 control.turnOn();109 control.bindImpl(tv2);110 control.turnOn();111
112 AbstractRemoteControl control_pc = newPcRemoteControl();113 control_pc.turnOn();114 }115 }
验证输出:
Sony is turned on.
Samsung is turned on.
Pc On
代码说明:
抽象化角色:远程控制,通过持有ITV接口实例,达到对电视万能控制
修正抽象化角色:pc的远程控制,有朝一日,电视消失了,证明抽象化角色还可以复用
实现化角色:ITV ,这个可以定义为抽象类,也可以定义为接口,个人倾向定义为接口,毕竟代码量少
具体实现化角色:各品牌的电视
何时持有对方引用?
阎宏博士java与模式一书省略了这一点,不少博客的例子是通过构造函数传参的方式获取对方引用,也许是为了图省事儿
我觉得恰是这些省略让人不太好体会这个模式的特点,因为这么干就说不清楚和抽象工厂模式的区别了,像下面的代码
Animal A = newcat()
A.run()
Animal B= newdog()
B.run()
持有对方引用通过调用一个普通方法
public voidbindImpl(ITV tv){this.tv =tv;
}
这样就只需要有一个实例,通过绑定不同的实现化对象,达到动态转换自己功能
类似于现实中,你有一个万能遥控器,通过点击某个电视品牌,你就能实现对具体电视的控制
参考: