结构型设计模模式---桥接模式

设计模式

序号内容链接地址
1设计模式七大原则https://blog.csdn.net/qq_39668819/article/details/115390615
2创建型设计模式–工厂模式https://blog.csdn.net/qq_39668819/article/details/115375928
3创建型设计模式–抽象工厂模式https://blog.csdn.net/qq_39668819/article/details/115390992
4创建型设计模式–单例模式https://blog.csdn.net/qq_39668819/article/details/115396191
5创建型设计模式–建造者模式https://blog.csdn.net/qq_39668819/article/details/115396212
6创建型设计模式—原型模式https://blog.csdn.net/qq_39668819/article/details/115396227
7结构型设计模式—代理模式https://blog.csdn.net/qq_39668819/article/details/115480346
8结构型设计模式—适配器模式https://blog.csdn.net/qq_39668819/article/details/115499090
9结构型设计模式—桥接模式https://blog.csdn.net/qq_39668819/article/details/115560823
10结构型设计模式—装饰模式https://blog.csdn.net/qq_39668819/article/details/115582291
11结构型设计模式—外观模式https://blog.csdn.net/qq_39668819/article/details/115643900
12结构型设计模式—享元模式https://blog.csdn.net/qq_39668819/article/details/115680930
13结构型设计模式—组合模式https://blog.csdn.net/qq_39668819/article/details/115720713
14行为型设计模式—模板方法模式https://blog.csdn.net/qq_39668819/article/details/115774426
15行为型设计模式—策略模式https://blog.csdn.net/qq_39668819/article/details/115804292
16行为型设计模式—命令模式https://blog.csdn.net/qq_39668819/article/details/115877361
17行为型设计模式—责任链模式https://blog.csdn.net/qq_39668819/article/details/115981287
18行为型设计模式—状态模式https://blog.csdn.net/qq_39668819/article/details/116077215
19行为型设计模式—观察者模式https://blog.csdn.net/qq_39668819/article/details/116141223
20行为型设计模式—中介者模式https://blog.csdn.net/qq_39668819/article/details/116177694
21行为型设计模式—迭代器模式https://blog.csdn.net/qq_39668819/article/details/116213033
22行为型设计模式—访问者模式https://blog.csdn.net/qq_39668819/article/details/116246907
23行为型设计模式—备忘录模式https://blog.csdn.net/qq_39668819/article/details/116333844
24行为型设计模式—解释器模式https://blog.csdn.net/qq_39668819/article/details/116379466
桥接模式

在现实生活中,某些事物具有两个或多个纬度的变化。如:手机既可以按品牌分,又可以按尺寸分,还可以按颜色分;文字既可以按字体分,也可以按字号分;图形可以按形状分,也可以按颜色分等等。如果使用继承的方式来描述,m种形状 和 n种颜色的图形就有 m*n 种组合,不但产生的子类繁多,而且扩展困难。而桥接模式则可以很好的解决这些问题。

定义与特点

桥接模式,将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变纬度的耦合。桥接模式遵循了 组合/聚合复用原则、里氏替换原则以及依赖倒置原则,最终实现了开闭原则,对修改关闭,对扩展开放。

这里简单介绍下 组合【也叫合成】/聚合复用原则:尽量使用组合/聚合,尽量不要使用类继承。

组合 和 聚合 都是关联的特殊种类。聚合表示一种弱的 ‘拥有’ 关系,体现的是 A 对象可以包含 B 对象,但是 B 对象不是 A 对象的一部分;组合则是一种强的 ‘拥有’ 关系,体现了严格的部分和整体的关系,部分和整体的生命周期是一样的。比方说:大雁有两个翅膀,翅膀与大雁是部分和整体的关系,并且它们的生命周期是相同的,于是大雁和翅膀就是组合关系。而大雁是群居动物,所以每只大雁都是属于一个雁群,一个雁群可以有多只大雁,所以大雁和雁群是聚合关系。

20210408234523551

组合/聚合复用原则的好处是:优先使用对象的组合/聚合将有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。

桥接模式优点:

  • 抽象与实现分离,扩展能力强
  • 符合开闭原则
  • 符合组合/聚合复用原则
  • 其实现细节对客户透明

缺点:

  • 由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,能正确地识别出系统中两个独立变化的维度,这增加了系统的理解与设计难度。
模式的结构

桥接模式主要角色如下:

  • 抽象化角色(Abstraction):定义抽象类,包含对实现化对象的引用。
  • 扩展抽象化角色(Refined Abstraction):是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
  • 实现化角色(Implementor):定义实现化角色的接口,供扩展抽象化角色调用。
  • 具体实现化角色(Concrete Implementor):给出实现化角色接口的具体实现。

其 UML 图:

20210408222725406

模式的使用

这里以用桥接模式模拟手机选购。

分析:手机有很多种,可以按品牌分、按系统分、按颜色分、按尺寸分等。存在多个纬度的变化,所以采用桥接模式来实现手机的选购比较合适。

本案例按品牌分为 “Huawei” 和 “Apple”,按系统分为 “android” 和 “ios”,按颜色分可选 “blou”、“red” 和 “yellow” 。可以按三个纬度分别定义为 品牌类、系统类、颜色类。

  • 颜色类(Color)是一个纬度,定义为实现化角色,它具有三个具体实现化角色:”blou“、“red”、“yellow”,通过 getColor() 方法选择颜色。

  • 系统类(MobilePhoneSystem)是另外一个纬度,定义为实现化角色,它具有两个具体实现化角色:”android“、”ios“,可以通过 getSystem()方法选择系统。

  • 品牌类(MobilePhoneBrand)是最后一个纬度,定义为抽象化角色,他有两个扩展抽象化角色:“Huawei” 和 “Apple”,它包含了颜色类对象 和 系统类对象,可以通过 getName() 方法选择相关系统和颜色的 “HuaweiPhone” 和 “ApplePhone”。

其结构图如下:

20210409173425397

/**
* 实现化角色-颜色
*/
public interface Color {
    String getColor();
}
/**
* 具体实现化角色-红色
*/
public class Red implements Color{

    @Override
    public String getColor() {
        return "red";
    }
}
/**
* 具体实现化角色-黄色
*/
public class Yellow implements Color{

    @Override
    public String getColor() {
        return "yellow";
    }
}
/**
* 具体实现化角色-蓝色
*/
public class Blou implements Color{

    @Override
    public String getColor() {
        return "blou";
    }
}

/**
* 实现化角色-系统
*/
interface MobilePhoneSystem {
    String getSystem();
}
/**
* 具体实现化角色-android系统
*/
public class AndroidSystem implements MobilePhoneSystem{

    @Override
    public String getSystem() {
        return "android";
    }
}
/**
* 具体实现化角色-ios系统
*/
public class IosSystem implements MobilePhoneSystem{

    @Override
    public String getSystem() {
       return "ios";
    }
}

/**
* 抽象化角色-手机品牌
*/
@Getter
@Setter
abstract class MobilePhoneBrand {

    /**
     * 聚合系统
     */
    protected MobilePhoneSystem mobilePhoneSystem;
    /**
     * 聚合颜色
     */
    protected Color color;

    /**
     * 获取手机
     * @return
     */
    public abstract String getName();
}
/**
* 扩展抽象化角色-华为品牌手机
*/
public class HuaweiPhone extends MobilePhoneBrand{

    @Override
    public String getName() {
        return mobilePhoneSystem.getSystem() + " system " + color.getColor() + " HuaweiPhone";
    }
}
/**
* 扩展抽象化角色-苹果品牌手机
*/
public class ApplePhone extends MobilePhoneBrand{

    @Override
    public String getName() {
        return mobilePhoneSystem.getSystem() + " system " + color.getColor() + " ApplePhone";
    }
}

/**
* 桥接模式测试
*/
public class BridgeTest {

    public static void main(String[] args) {
        MobilePhoneBrand huawei = new HuaweiPhone();
        huawei.setMobilePhoneSystem(new AndroidSystem());
        huawei.setColor(new Blou());

        System.out.println(huawei.getName());

        System.out.println();
        MobilePhoneBrand apple = new ApplePhone();
        apple.setMobilePhoneSystem(new IosSystem());
        apple.setColor(new Red());
        System.out.println(apple.getName());
    }
}

运行程序,结果如下:我们可以通过设置不同的实现化角色来获取不同的手机,而且实现 m * n 种组合也不需要像继承那样需要实现 m * n 个子类导致类的爆炸了。

20210409164314865

模式的应用场景

桥接模式通常适用于以下场景:

  • 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
  • 当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时。
  • 当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。

桥接模式的一个常见使用场景就是替换继承。我们知道,继承拥有很多优点,比如,抽象、封装、多态等,父类封装共性,子类实现特性。继承可以很好的实现代码复用(封装)的功能,但这也是继承的一大缺点。

因为父类拥有的方法,子类也会继承得到,无论子类需不需要,这说明继承具备强侵入性(父类代码侵入子类),同时会导致子类臃肿。因此,在设计模式中,有一个原则为优先使用组合/聚合,而不是继承。

很多时候,我们分不清该使用继承还是组合/聚合或其他方式等,其实可以从现实语义进行思考。因为软件最终还是提供给现实生活中的人使用的,是服务于人类社会的,软件是具备现实场景的。当我们从纯代码角度无法看清问题时,现实角度可能会提供更加开阔的思路。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值