9,桥接模式(Bridge)
9.1,问题引入_手机类型
-
现在对不同类型不同品牌的手机实现操作编程,如下手机外观类型和对应品牌:
-
则需要编写的代码类图可能如下:
-
带来的问题如下:
- 如果我们需要添加一个手机,则需要在各个类型下添加手机
- 如果我们需要添加一个品牌,则需要在该品牌下添加各个类型的手机
-
这样会造成基本的类爆炸,可以使用桥接模式对实现(手机品牌)和抽象(手机类型)分别进行向上抽取,通过抽象依赖实现的方式增强代码维护性
9.2,基本介绍
- 桥接模式是指将实现和抽象放在两个不同的类层次中,并可以进行独立改变。桥接模式是一种结构性设计模式
- 桥接模式基于类的最小设计原则,使用封装、聚合和继承等行为让不同的类承担不同的职责。主要特点是把**抽象(Abstraction)和实现(Implementation)**分离开来,从而保证各部分的独立性及功能扩展
9.3,类图
- 对抽象和实现进行拆分,拆分为两个独立的模块,并通过组合关系关联在一起
- 抽象模块是手机类型模块,以
PhoneType
为顶层抽象类,并派生出UpRightType
和FlodedType
等具体类型类 - 实现模块是手机品牌模块,以
IBrand
为顶层接口,并派生出各个手机品牌 - 手机类型组合手机品牌,将手机品牌作为其内部的构造参数
- 客户端在进行具体操作时,默认先适配机型,再适配具体手机
9.4,代码示例
-
实现模块顶层接口:
IBrand
package com.self.designmode.bridge; /** * 手机品牌: 实现层顶层接口 * @author PJ_ZHANG * @create 2020-07-27 17:51 **/ public interface IBrand { void open(); void call(); void close(); }
-
实现模块实现类_1:
Huawei
package com.self.designmode.bridge; /** * 具体实现类: 华为手机 * @author PJ_ZHANG * @create 2020-07-27 17:55 **/ public class Huawei implements IBrand { @Override public void open() { System.out.println("华为手机开机..."); } @Override public void call() { System.out.println("华为手机打电话..."); } @Override public void close() { System.out.println("华为手机关机"); } }
-
实现模块实现类_2:
Xiaomi
package com.self.designmode.bridge; /** * 具体实现类: 小米手机 * @author PJ_ZHANG * @create 2020-07-27 17:56 **/ public class Xiaomi implements IBrand { @Override public void open() { System.out.println("小米手机开机..."); } @Override public void call() { System.out.println("小米手机打电话..."); } @Override public void close() { System.out.println("小米手机关机"); } }
-
抽象模块顶层抽象类:
PhoneType
package com.self.designmode.bridge; import com.self.designmode.adapter.interfaceadapter.Phone; /** * 手机类型: 抽象层顶层类 * @author PJ_ZHANG * @create 2020-07-27 17:53 **/ public abstract class PhoneType { private IBrand brand; public PhoneType(IBrand brand) { this.brand = brand; } public void open() { brand.open(); } public void call() { brand.call(); } public void close() { brand.close(); } }
-
抽象模块子类_1:
FlodedType
package com.self.designmode.bridge; /** * 抽象子类: 旋转类型手机 * @author PJ_ZHANG * @create 2020-07-27 17:57 **/ public class FlodedType extends PhoneType{ public FlodedType(IBrand brand) { super(brand); } public void open() { super.open(); System.out.println("旋转类型手机开机..."); } public void call() { super.call(); System.out.println("旋转类型手机打电话..."); } public void close() { super.close(); System.out.println("旋转类型手机关机..."); } }
-
抽象模块子类_2:
UpRightType
package com.self.designmode.bridge; /** * 抽象子类: 直立类型手机 * @author PJ_ZHANG * @create 2020-07-27 17:57 **/ public class UpRightType extends PhoneType{ public UpRightType(IBrand brand) { super(brand); } public void open() { super.open(); System.out.println("直立类型手机开机..."); } public void call() { super.call(); System.out.println("直立类型手机打电话..."); } public void close() { super.close(); System.out.println("直立类型手机关机..."); } }
-
客户端:
Client
package com.self.designmode.bridge; /** * @author PJ_ZHANG * @create 2020-07-27 17:58 **/ public class Client { public static void main(String[] args) { PhoneType phoneType = new UpRightType(new Huawei()); phoneType.call(); phoneType = new FlodedType(new Xiaomi()); phoneType.open(); } }
9.5,注意事项和细节
- 实现了抽象部分和实现部分的分离,极大的提供了系统的灵活性,有助于系统的分层化设计,从而产生更好的结构化系统
- 对于系统的高层部分,只需要知道抽象部分和实现部分的接口即可,具体业务由底层完成
- 桥接模式替代多层继承关系,可以有效的介绍子类数量,降低系统管理和维护成本
- 桥接模式的引入增加了系统的理解和设计难度,因为组合关联关系在抽象层,所以需要面向抽象层进行编程
- 桥接模式需要准确的识别出系统中两个维度(抽象层,实现层),因此其使用场景有一定的局限性
9.6,常见使用场景
- 银行转账系统
- 转账分类:网上银行,柜台转账,ATM转账
- 用户类型:普通用户,会员用户,金卡用户
- 消息管理
- 消息类型:即时消息,延时消息
- 消息分类:手机短信,右键信息,QQ消息…