模式说明
当一个事物可以通过多个维度描述时,要避免多个维度层层继承该事物的抽象类,而应该将这些不同的维度从事物中分离出来独立变化。例如电脑可以通过不同品牌和不同软件描述,可以将电脑作为一个PC抽象类,以品牌为主体,不同品牌继承该PC类如ApplePC。软件分离出来成为一个独立的抽象类Software,具体软件继承该Software抽象类,例如Browser类。在PC抽象类中以组合形式拥有Software,并通过调用Software的方法,实施Software中的行为。在UML图中分离事物抽象类通过带组合箭头的线与主体事物抽象类连接,故名桥接。
本示例演示上述PC场景。如果希望增加一个华为品牌PC只需增加继承PC类的HuaweiPC类即可,无需改动其他类。同理希望增加视频软件时,也只需要增加VideoPlayer类而无需关注品牌。这就是各自独立变化。另,本示例中主体事物PC只持有一个Software实例,如果想同时持有多个Software实例,可以声明为集合类型(如List),然后增加相应的add方法。
结构
抽象主体事物类
主体事物,类内声明一个以protected修饰的分离事物(以抽象类型声明)。声明一个用于实施分离事物行为的抽象方法。
具体主体事物类
继承抽象主体事物类,实现抽象方法。
抽象分离事物类
能够描述主体事物的某个维度的事物,声明自己的行为。
具体分离事物类
继承抽象分离事物类,实现抽象方法。
代码示例
package com.yukiyama.pattern.structure;/*** 桥接模式*/public class BridgeDemo {public static void main(String[] args) {// 声明一个PC(主体事物)PC pc = new ApplePC();// 声明一个软件(分离事物)Software soft1 = new Browser();// 将软件组合进PC中(主体持有分离)pc.setSoftware(soft1);// 通过调用主体事物的方法来间接执行分离事物的方法// 输出"启动: Browser"pc.run();// 增加一个软件后,同上Software soft2 = new MusicPlayer();pc.setSoftware(soft2);// 输出"启动: MusicPlayer"pc.run();}}/*** 主体事物抽象类* 以PC为例,内部声明protected修饰的分离事物Software。非抽象方法* setSoftware()传入分离事物使得主体持有分离。声明用于实施Software* 行为抽象方法run()。*/abstract class PC{protected Software soft;public void setSoftware(Software soft) {this.soft = soft;}public abstract void run();}/*** 主体事物具体类* 继承抽象主体事物类,实现抽象方法run,内部实际调用Software自身的run。*/class ApplePC extends PC{@Overridepublic void run() {this.soft.run();}}/*** 抽象分离事物类* 有自身的属性和方法。* 下例是从软件维度描述PC的软件抽象类。*/abstract class Software{private String name;public void setName(String name) {this.name = name;}public String getName() {return name;}public abstract void run();}/*** 具体分离事物类* 继承抽象分离事物类,实现抽抽象方法。* 下例是浏览器类。*/class Browser extends Software{public Browser() {this.setName("Browser");}@Overridepublic void run() {System.out.println("启动: "+this.getName());}}/*** 具体分离事物类* 下例是音乐播放器类。*/class MusicPlayer extends Software{public MusicPlayer() {this.setName("MusicPlayer");}@Overridepublic void run() {System.out.println("启动: "+this.getName());}}
