Java设计模式之结构型模式 | 桥接模式

56 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 14 天,点击查看活动详情

觉得对你有益的小伙伴记得点个赞+关注

后续完整内容持续更新中

希望一起交流的欢迎发邮件至javalyhn@163.com

1. 桥接模式定义

将抽象与实现解耦,使两者都可以独立变化

在现实生活中,某些类具有两个或多个维度的变化,如图形既可按形状分,又可按颜色分。如何设计类似于 Photoshop 这样的软件,能画不同形状和不同颜色的图形呢?如果用继承方式,m 种形状和 n 种颜色的图形就有 m×n 种,不但对应的子类很多,而且扩展困难。不同颜色和字体的文字、不同品牌和功率的汽车

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

image.png

2. 桥接模式中的角色定义

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

3. 桥接模式使用场景

  1. 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
  2. 当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时。
  3. 当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。
  4. InputStreamReader桥接模式。An InputStreamReader is a bridge from byte streams to character streams
  5. InputStreamReader 桥接+适配器

4. 桥接模式实现

我们给定以下手机销售情景。

image.png

AbstractPhone

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

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


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

    public void setSale(AbstractSale sale) {
        this.sale = sale;
    }
}

IPhone

public class IPhone  extends AbstractPhone{

    @Override
    String getPhone() {
        return "IPhone:"+sale.getSaleInfo();
    }
}

MiPhone

public class MiPhone extends AbstractPhone{
    @Override
    String getPhone() {
        return "小米:";
    }
}

AbstractSale

/**
 * 抽象销售渠道
 * 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(){
        //都不一样
    }
}

OnlineSale

/**
 * 线上渠道
 */
public class OnlineSale extends AbstractSale{
    public OnlineSale(String type, Integer price) {
        super(type, price);
    }
}

OfflineSale

/**
 * 线下渠道
 */
public class OfflineSale  extends AbstractSale{
    public OfflineSale(String type, Integer price) {
        super(type, price);
    }
}

StudentSale

public class StudentSale extends AbstractSale{
    public StudentSale(String type, Integer price) {
        super(type, price);
    }
}

MainTest

/**
 * 省去了创建很多类
 */
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);

    }
}

image.png

可见我们省去了很多类的创建

5. 桥接模式的优点

  1. 抽象和实现分离:这也是桥接模式的主要特点,他完全是为了解决继承的缺点而提出的设计模式。
  2. 优秀的扩充能力
  3. 实现细节对客户透明:客户不用关心细节的实现,他已经由抽象层通过聚合关系完成了封装。

6. 桥接模式注意事项

  1. 桥接模式的引入增加了系统的理解和设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计和编程
  2. 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围有一定的局限性,即需要有这样的应用场景.