「补课」进行时:设计模式系列java
设计模式的最后一篇文章,仍是让我这个拖延症晚期的患者把时间拖到了 2020 年的最后一天。编程
虽然是最后一篇,但并非最难的一个模式,比较复杂的两个模式已经在前面介绍过了,一个是访问者模式,另外一个是解释器模式。设计模式
那么什么是桥梁模式?ide
桥梁模式(Bridge Pattern) 也叫作桥接模式, 是一个比较简单的模式, 其定义以下:Decouple an abstraction from its implementation so that the two can vary independently.(将抽象和实现解耦, 使得二者能够独立地变化。 )函数
桥梁模式的重点是在「解耦」上, 如何让它们二者解耦是桥梁模式的重点,this
桥梁模式中的几个名词比较拗口,核心就一句话:抽象角色引用实现角色,或者说抽象角色的部分实现是由实现角色完成的。设计
实现化角色:code
public interface Implementor { // 基本方法 void doSomething(); void doAnything(); }
具体实现化角色:对象
public class ConcreteImplementor1 implements Implementor { @Override public void doSomething() { } @Override public void doAnything() { } } public class ConcreteImplementor2 implements Implementor { @Override public void doSomething() { } @Override public void doAnything() { } }
抽象化角色:blog
public abstract class Abstraction { // 定义对实现化角色的引用 private Implementor impl; // 约束子类必须实现该构造函数 public Abstraction(Implementor impl){ this.impl = impl; } // 自身的行为和属性 public void request(){ this.impl.doSomething(); } // 得到实现化角色 public Implementor getImpl(){ return impl; } }
具体抽象化角色:
public class RefinedAbstraction extends Abstraction { // 覆写构造函数 public RefinedAbstraction(Implementor impl) { super(impl); } // 修正父类的行为 @Override public void request(){ // 业务处理 super.request(); super.getImpl().doAnything(); } }
客户端类:
public class Client { public static void main(String[] args) { // 定义一个实现化角色 Implementor imp = new ConcreteImplementor1(); // 定义一个抽象化角色 Abstraction abs = new RefinedAbstraction(imp); // 执行行文 abs.request(); } }
会增长系统的理解与设计难度。因为聚合关联关系创建在抽象层,要求开发者针对抽象进行设计与编程。
在桥接模式中要把握的很重要的一点就是:类的继承关系和类的组合/聚合关系,什么时候应该考虑使用何种关系。是否是在编程过程当中一味地使用类的继承关系就表明这就是面向对象编程了?有时候并非这样, Java 的类继承设计成单继承模式我想应该就是不想把类的继承关系搞得过于复杂,实际上咱们应该优先使用对象组合/聚合,而不是类继承。
类继承没必要多说,先来看看何为组合/聚合关系。
聚合体现的是「弱」的拥有关系,好比雁群能够包含大雁,但雁群不是大雁的一部分。组合体现的是「强」的拥有关系,或者体现的是部分与总体的关系,经过一对翅膀组合成大雁,翅膀是部分,大雁是总体。
咱们如今每天使用的一个电器:手机,手机有手机品牌和手机软件等等,每一个手机品牌都有多款软件。
这个案例若是使用继承关系的话,无论是已手机品牌仍是手机软件做为父类,都会对后续的扩展形成很大的影响,若是咱们使用桥梁模式,使用对象的组合/聚合,类图是下面这样:
经过UML类结构图咱们能够看到手机品牌和手机软件成功解耦,新增功能并不影响其手机品牌,新增手机品牌也不会影响到手机软件,其中的奥秘就在于利用了聚合而不是继承。
代码以下:
手机品牌抽象类:
public abstract class HandsetBrand { protected HandsetSoft soft; // 设置手机软件 public void setHandsetSoft(HandsetSoft soft) { this.soft = soft; } // 运行 abstract void run(); }
手机软件抽象类:
public abstract class HandsetSoft { abstract void run(); }
各种手机品牌实现类:
public class HandsetBrandA extends HandsetBrand { @Override void run() { super.soft.run(); } } public class HandsetBrandB extends HandsetBrand{ @Override void run() { super.soft.run(); } }
手机软件实现类:
public class HandsetGame extends HandsetSoft{ @Override void run() { System.out.println("运行手机游戏"); } } public class HandsetAddressList extends HandsetSoft{ @Override void run() { System.out.println("运行手机通信录"); } }
客户端类:
public class Client { public static void main(String[] args) { HandsetBrand ab; // 使用 A 品牌手机 ab = new HandsetBrandA(); System.out.println("A品牌手机:"); ab.setHandsetSoft(new HandsetGame()); ab.run(); ab.setHandsetSoft(new HandsetAddressList()); ab.run(); // 使用 B 品牌手机 ab = new HandsetBrandB(); System.out.println("B品牌手机:"); ab.setHandsetSoft(new HandsetGame()); ab.run(); ab.setHandsetSoft(new HandsetAddressList()); ab.run(); } }
执行结果以下:
A品牌手机: 运行手机游戏 运行手机通信录 B品牌手机: 运行手机游戏 运行手机通信录