模式说明

当一个事物可以通过多个维度描述时,要避免多个维度层层继承该事物的抽象类,而应该将这些不同的维度从事物中分离出来独立变化。例如电脑可以通过不同品牌和不同软件描述,可以将电脑作为一个PC抽象类,以品牌为主体,不同品牌继承该PC类如ApplePC。软件分离出来成为一个独立的抽象类Software,具体软件继承该Software抽象类,例如Browser类。在PC抽象类中以组合形式拥有Software,并通过调用Software的方法,实施Software中的行为。在UML图中分离事物抽象类通过带组合箭头的线与主体事物抽象类连接,故名桥接。

本示例演示上述PC场景。如果希望增加一个华为品牌PC只需增加继承PC类的HuaweiPC类即可,无需改动其他类。同理希望增加视频软件时,也只需要增加VideoPlayer类而无需关注品牌。这就是各自独立变化。另,本示例中主体事物PC只持有一个Software实例,如果想同时持有多个Software实例,可以声明为集合类型(如List),然后增加相应的add方法。

结构

抽象主体事物类
主体事物,类内声明一个以protected修饰的分离事物(以抽象类型声明)。声明一个用于实施分离事物行为的抽象方法。
具体主体事物类
继承抽象主体事物类,实现抽象方法。
抽象分离事物类
能够描述主体事物的某个维度的事物,声明自己的行为。
具体分离事物类
继承抽象分离事物类,实现抽象方法。

代码示例

  1. package com.yukiyama.pattern.structure;
  2. /**
  3. * 桥接模式
  4. */
  5. public class BridgeDemo {
  6. public static void main(String[] args) {
  7. // 声明一个PC(主体事物)
  8. PC pc = new ApplePC();
  9. // 声明一个软件(分离事物)
  10. Software soft1 = new Browser();
  11. // 将软件组合进PC中(主体持有分离)
  12. pc.setSoftware(soft1);
  13. // 通过调用主体事物的方法来间接执行分离事物的方法
  14. // 输出"启动: Browser"
  15. pc.run();
  16. // 增加一个软件后,同上
  17. Software soft2 = new MusicPlayer();
  18. pc.setSoftware(soft2);
  19. // 输出"启动: MusicPlayer"
  20. pc.run();
  21. }
  22. }
  23. /**
  24. * 主体事物抽象类
  25. * 以PC为例,内部声明protected修饰的分离事物Software。非抽象方法
  26. * setSoftware()传入分离事物使得主体持有分离。声明用于实施Software
  27. * 行为抽象方法run()。
  28. */
  29. abstract class PC{
  30. protected Software soft;
  31. public void setSoftware(Software soft) {
  32. this.soft = soft;
  33. }
  34. public abstract void run();
  35. }
  36. /**
  37. * 主体事物具体类
  38. * 继承抽象主体事物类,实现抽象方法run,内部实际调用Software自身的run。
  39. */
  40. class ApplePC extends PC{
  41. @Override
  42. public void run() {
  43. this.soft.run();
  44. }
  45. }
  46. /**
  47. * 抽象分离事物类
  48. * 有自身的属性和方法。
  49. * 下例是从软件维度描述PC的软件抽象类。
  50. */
  51. abstract class Software{
  52. private String name;
  53. public void setName(String name) {
  54. this.name = name;
  55. }
  56. public String getName() {
  57. return name;
  58. }
  59. public abstract void run();
  60. }
  61. /**
  62. * 具体分离事物类
  63. * 继承抽象分离事物类,实现抽抽象方法。
  64. * 下例是浏览器类。
  65. */
  66. class Browser extends Software{
  67. public Browser() {
  68. this.setName("Browser");
  69. }
  70. @Override
  71. public void run() {
  72. System.out.println("启动: "+this.getName());
  73. }
  74. }
  75. /**
  76. * 具体分离事物类
  77. * 下例是音乐播放器类。
  78. */
  79. class MusicPlayer extends Software{
  80. public MusicPlayer() {
  81. this.setName("MusicPlayer");
  82. }
  83. @Override
  84. public void run() {
  85. System.out.println("启动: "+this.getName());
  86. }
  87. }