桥接模式

将抽象与实现解耦,使两者都可以独立变化
在现实生活中,某些类具有两个或多个维度的变化,如图形既可按形状分,又可按颜色分。如何设计类似于 Photoshop 这样的软件,能画不同形状和不同颜色的图形呢?如果用继承方式,m 种形状和 n 种颜色的图形就有 m×n 种,不但对应的子类很多,而且扩展困难。不同颜色和字体的文字、不同品牌和功率的汽车
桥接将继承转为关联,降低类之间的耦合度,减少代码量

  1. ![](https://image.imxyu.cn/file/image-20211018210814552.png#alt=image-20211018210814552)

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

结构型-桥接模式 - 图1

以前的实现:因为线上和线下手机的价格不同,手机还分很多型号,如果维度变多,子类会成倍的增长

结构型-桥接模式 - 图2

我们可能还有针对不同渠道的销售方法,因此我们需要将这个维度抽离出来,通过桥接(组合的方式)引入

  1. public abstract class Phone {
  2. // abstract int price();如果这么写会需要多个实现类,线上价格、线下价格
  3. Sale sale; //分离渠道,将会变化的一个维度抽取出来,这里就是桥接
  4. //获取手机的信息
  5. abstract String getPhoneInfo();
  6. void setSale(Sale sale){
  7. this.sale=sale;
  8. }
  9. }
  1. /**
  2. * 渠道类,包含渠道的类型,和相应的价格
  3. */
  4. public abstract class Sale {
  5. private String type;
  6. private Integer price;
  7. public Sale(String type,Integer price){
  8. this.price=price;
  9. this.type=type;
  10. }
  11. String getSaleInfo(){
  12. return "渠道"+type+"价格=》"+price;
  13. }
  14. abstract void howToSale(); //可能还会有针对不同的渠道怎么卖的方法
  15. }
  1. // iphone手机
  2. public class Iphone extends Phone{
  3. @Override
  4. String getPhoneInfo() {
  5. return sale.getSaleInfo();
  6. }
  7. }
  8. //...各种型号的手机
  1. public class MainTest {
  2. public static void main(String[] args) {
  3. Phone iphone=new Iphone();
  4. Sale sale = new OffSale("线下", 999);
  5. iphone.setSale(sale);
  6. String phoneInfo = iphone.getPhoneInfo();
  7. System.out.println(phoneInfo);
  8. }
  9. }

当我们要扩展渠道时,例如我们要添加一个学生优惠渠道,只需要添加一个StudentSale类继承原Sale即可

使用场景

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