设计模式之桥接模式

目录

[1. 概念](#1. 概念)

[2. 代码实现](#2. 代码实现)

[3. 应用场景](#3. 应用场景)


**桥接模式(Bridge Pattern)**也是我们结构型设计模式的一种,桥接模式整体来说对于开发者需要深刻理解好抽象类这个概念,而且比较考验在开发前就要设计好桥接点来进行开发,所以整体的理解难度我认为是比较高,接下来我将从概念和一个示例来演示该模式。

1. 概念

桥接模式就是将抽象与实现解藕,使两者都可以独立变化。在现实生活中,某些类具有两个或多个维度的变化,如图形既可按形状分,又可按颜色分。如何设计类似于Photoshop这样的软件,能画不同形状和不同颜色的图形呢?如果用继承的方式,m种形状和n种颜色的图形就有m✖️n种,不但对应的子类很多,而且扩展极其困难。不同颜色和字体的文字、不同品牌和功率的汽车...

桥接模式将继承转为关联,降低类之间的耦合度,减少代码量。

桥接(Bridge)模式包含以下主要角色:

  • 系统设计期间,如果这个类里面的一些东西,会扩展很多,这个东西就应该分离出来
  • 抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化对象的引用。
  • 扩展抽象化(Refined Abstraction)角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
  • 实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。

2. 代码实现

这里我们举一个电商手机售卖的例子,比如说我们的电商平台需要卖手机,但是手机其实有很多品牌,每个品牌的价格都不一样;同时手机可以通过不同渠道进行贩卖,每种贩卖渠道的价钱也不一样,那么如果不进行合理的设计直接编写的话,我们可能需要实现m✖️n个类,这对于我们整个系统来说扩展性以及可读性极差,这里我们就可以进行使用桥接模式进行设计。

那么我们可以对手机这个产品进行抽象,同时我们也可以将渠道进行抽象,但是注意,不同的渠道对于一个手机来说,可能就是一个属性(这里理解可能有些困难:因为不同的渠道影响着手机的价格,那么其实是在改变手机自身的状态,所以我们可以把渠道看作手机的一个属性),这其实就是我们需要注意的,这里的渠道就是我们桥接关注点。

java 复制代码
/**
 * 1、抽象手机类
 *  手机有各种销售渠道价格都不一样
 *
 */
public abstract class AbstractPhone {

    //桥接在此.....设计期间就得想好
    //【真正会引起此类变化的一个维度直接抽取出来,通过组合的方式接起来】
    //桥接+适配器 ...
    AbstractSale sale; //分离渠道【桥接的关注点】
//    abstract int getPrice();  如果这么写需要多少个实现。违反开闭原则


    /**
     * 当前手机的描述
     * @return
     */
    abstract String getPhone();

    public void setSale(AbstractSale sale) {
        this.sale = sale;
    }
}
java 复制代码
/**
 * 抽象销售渠道
 * PhoneOnSale  ==howToSale
 * PhoneOffSale == howToSale
 * PhoneStudentSale = howToSale
 * PhonePDD == howToSale
 *
 *
 */
public abstract class AbstractSale {

    private String type;
    private Integer price;
    public AbstractSale(String type,Integer price){
        this.type = type;
        this.price = price;
    }

    String getSaleInfo(){
        return "渠道:"+type+"==>"+"价格:"+price;
    }

    void howToSale(){
        //都不一样
    }
}

那么接下来,我们可以为不同种的渠道进行抽象类的实现,这里主要实现线上渠道与线下渠道还有学生渠道三种:

java 复制代码
/**
 * 线上渠道
 */
public class OnlineSale extends AbstractSale{
    public OnlineSale(String type, Integer price) {
        super(type, price);
    }
}
java 复制代码
/**
 * 线下渠道
 */
public class OfflineSale  extends AbstractSale{
    public OfflineSale(String type, Integer price) {
        super(type, price);
    }
}
java 复制代码
public class StudentSale extends AbstractSale{
    public StudentSale(String type, Integer price) {
        super(type, price);
    }
}

接下来我们在对手机的不同品牌来进行实现抽象类:

java 复制代码
public class IPhone  extends AbstractPhone{

    @Override
    String getPhone() {
        return "IPhone:"+sale.getSaleInfo();
    }
}
java 复制代码
public class MiPhone extends AbstractPhone{
    @Override
    String getPhone() {
        return "小米:";
    }
}

这样我们就可以来编写我们的环境类(测试类或者外部组件调用类):

java 复制代码
public class MainTest {

    public static void main(String[] args) {

        IPhone iPhone = new IPhone();
        iPhone.setSale(new StudentSale("学生",1));


        String phone = iPhone.getPhone();
        System.out.println(phone);

    }
}

这里我们就可以通过创建不同的渠道,通过该渠道中的价钱属性来定义不同品牌的手机在不同渠道中的价钱信息了,这样就免去了我们上述所提到n✖️m创建类的efforts了。

3. 应用场景

  • 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
  • 当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时。
  • 当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。
  • InputStreamReader桥接模式。An InputStreamReader is a bridge from byte streams to character streams:
  • InputStreamReader 桥接+适配器
  • ...
相关推荐
我命由我123452 小时前
Kotlin 数据容器 - List(List 概述、创建 List、List 核心特性、List 元素访问、List 遍历)
java·开发语言·jvm·windows·java-ee·kotlin·list
武子康4 小时前
Java-80 深入浅出 RPC Dubbo 动态服务降级:从雪崩防护到配置中心秒级生效
java·分布式·后端·spring·微服务·rpc·dubbo
YuTaoShao7 小时前
【LeetCode 热题 100】131. 分割回文串——回溯
java·算法·leetcode·深度优先
源码_V_saaskw7 小时前
JAVA图文短视频交友+自营商城系统源码支持小程序+Android+IOS+H5
java·微信小程序·小程序·uni-app·音视频·交友
超浪的晨7 小时前
Java UDP 通信详解:从基础到实战,彻底掌握无连接网络编程
java·开发语言·后端·学习·个人开发
双力臂4048 小时前
Spring Boot 单元测试进阶:JUnit5 + Mock测试与切片测试实战及覆盖率报告生成
java·spring boot·后端·单元测试
Edingbrugh.南空8 小时前
Aerospike与Redis深度对比:从架构到性能的全方位解析
java·开发语言·spring
QQ_4376643149 小时前
C++11 右值引用 Lambda 表达式
java·开发语言·c++
永卿0019 小时前
设计模式-迭代器模式
java·设计模式·迭代器模式
使二颗心免于哀伤9 小时前
《设计模式之禅》笔记摘录 - 10.装饰模式
笔记·设计模式