一. 概述
桥接模式(Bridge Pattern)是一种结构型设计模式,用于将抽象部分与其实现部分分离,使它们可以独立地变化。桥接模式主要目的是解决当一个类存在多个继承等级时,由于继承带来的耦合问题,以及扩展性不足的问题。
- 定义:将抽象部分与他的具体实现部分分离,使它们都可以独立的变化,通过组合的方式建立两个类之间的联系,而不是继承
- 类型:结构性。
二. 使用场景
- 抽象和具体实现之间增加更多的灵活性
- 一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要独立进行扩展
- 不希望使用继承,或因为多层继承导致系统类的个数剧增
三. 桥接模式的原理及代码示例
1. 桥接模式的组成部分:
- 抽象化(Abstraction)角色 :主要负责定义出该角色的行为 ,并包含一个对实现化对象的引用。
- 扩展抽象化(RefinedAbstraction)角色 :是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
- 实现化(Implementor)角色 :定义实现化角色的接口,包含角色必须的行为和属性,并供扩展抽象化角色调用。
- 具体实现化(Concrete Implementor)角色 :给出实现化角色接口的具体实现。
2. UML图
3. 桥接模式具体实现步骤:
- 定义实手机接口
- 实现手机接口(不同的品牌添加不同的实现类)
- 定义抽象类(通过这个抽象类实现抽象和具体实现分离)
- 实现抽象类。
- 在扩展抽象化角色中,组合实现化角色的实例,并实现具体的行为。
4. 示例代码
代码示例以手机和产地为例,手机分为国产品牌和美国品牌,国产手机可分为华为,vivo等,美国有苹果手机,谷歌手机等,对国产手机的添加只需添加一个具体实现类即可,如果想要添加一个韩国的手机则需要对抽象类进行继承实现。
- 1. 定义接口
package com.seata; /** * 文件名:dnm * 创建者: * 创建时间: * 描述:手机品牌接口 */ public interface IMobilePhoneInterface { void showMobilePhone(); }
- 2. 实现类(华为手机)
package com.seata; /** * 文件名:HuaWeiMobilePhone * 创建者: * 创建时间: * 描述:华为品牌手机 */ public class HuaWeiMobilePhone implements IMobilePhoneInterface{ @Override public void showMobilePhone() { System.out.println("华为手机"); } }
- 3. 实现类(苹果手机)
package com.seata; /** * 文件名:AmericaMobilePhone * 创建者: * 创建时间: * 描述:苹果手机 */ public class AppleMobilePhone implements IMobilePhoneInterface{ @Override public void showMobilePhone() { System.out.println("苹果手机"); } }
- 4. 定义抽象类
package com.seata; /** * 文件名:CountryAbstract * 创建者: * 创建时间: * 描述:抽象类 */ public abstract class CountryAbstract { // 持有接口属性 protected IMobilePhoneInterface phoneInterface; public CountryAbstract(IMobilePhoneInterface phoneInterface){ this.phoneInterface = phoneInterface; } abstract void showCountry(); }
- 5. 国产品牌
package com.seata; /** * 文件名:China * 创建者: * 创建时间: * 描述:国产品牌 */ public class China extends CountryAbstract{ public China(IMobilePhoneInterface phoneInterface){ super(phoneInterface); } @Override void showCountry() { phoneInterface.showMobilePhone(); System.out.println("国产品牌"); } }
- 6. 美国品牌
package com.seata; /** * 文件名:America * 创建者: * 创建时间: * 描述:美国品牌 */ public class America extends CountryAbstract{ public America(IMobilePhoneInterface phoneInterface){ super(phoneInterface); } @Override void showCountry() { phoneInterface.showMobilePhone(); System.out.println("美国品牌"); } }
- 7. 测试类
package com.seata; /** * 文件名:Test * 创建者: * 创建时间: * 描述: 测试类 */ public class Test { public static void main(String[] args) { //国产品牌 China countryAbstract = new China(new HuaWeiMobilePhone()); countryAbstract.showCountry(); System.out.println("======================================="); //美国品牌 America anAbstract = new America(new AppleMobilePhone()); anAbstract.showCountry(); } }
测试结果
- 8. 假如我们想要添加一个国产 vivo 手机,只需要在添加一个实现类即可
package com.seata; /** * 文件名:VivoMobilePhone * 创建者: * 创建时间: * 描述:vivo手机 */ public class VivoMobilePhone implements IMobilePhoneInterface{ @Override public void showMobilePhone() { System.out.println("vivo 手机"); } }
测试类添加
package com.seata; /** * 文件名:Test * 创建者: * 创建时间: * 描述: 测试类 */ public class Test { public static void main(String[] args) { //国产品牌 China countryAbstract = new China(new HuaWeiMobilePhone()); countryAbstract.showCountry(); System.out.println("======================================="); //美国品牌 America anAbstract = new America(new AppleMobilePhone()); anAbstract.showCountry(); System.out.println("======================================="); //Vivo品牌 China china = new China(new VivoMobilePhone()); china.showCountry(); } }
测试结果
- 9.假如我们想要添加一个韩国的三星品牌手机,这个时候需要添加抽象类的实现类,再添加一个具体实现类
添加抽象类的实现类
package com.seata; /** * 文件名:BnagZiMobilePhone * 创建者: * 创建时间: * 描述:韩国 */ public class BnagZi extends CountryAbstract{ public BnagZi(IMobilePhoneInterface phoneInterface){ super(phoneInterface); } @Override void showCountry() { phoneInterface.showMobilePhone(); System.out.println("韩国品牌"); } }
添加手机品牌具体实现类
package com.seata; /** * 文件名:BnagZiMobilePhone * 创建者: * 创建时间: * 描述:三星手机 */ public class SanXingMobilePhone implements IMobilePhoneInterface{ @Override public void showMobilePhone() { System.out.println("三星手机"); } }
测试类
package com.seata; /** * 文件名:Test * 创建者: * 创建时间: * 描述: 测试类 */ public class Test { public static void main(String[] args) { //国产品牌 China countryAbstract = new China(new HuaWeiMobilePhone()); countryAbstract.showCountry(); System.out.println("======================================="); //美国品牌 America anAbstract = new America(new AppleMobilePhone()); anAbstract.showCountry(); System.out.println("======================================="); //Vivo品牌 China china = new China(new VivoMobilePhone()); china.showCountry(); System.out.println("======================================="); //三星品牌 BnagZi bnagZi = new BnagZi(new SanXingMobilePhone()); bnagZi.showCountry(); } }
测试结果
四. 桥接模式的优缺点
优点:
- 分离抽象部分及其具体实现部分,解耦抽象与实现的绑定关系
- 提高了系统的可扩展性
- 符合开闭原则
- 符合合成复用原则
缺点:
- 增加了系统的理解与设计难度
- 需要正确的识别出系统中两个独立变化的维度