九、设计模式之桥接模式


在这里插入图片描述

九、设计模式之桥接模式

在这里插入图片描述

所属类型定义
结构型桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interfce)模式。

难度: ⭐️ ⭐️ ⭐️ ⭐️ ⭐️

能帮我们干什么?

目的

将抽象与实现分离,使它们可以独立地变化

主要解决什么问题?

多维度情况下,各个维度扩展。
在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活

优缺点

优点

1、抽象和实现的分离。
2、优秀的扩展能力。
3、实现细节对客户透明。

缺点:
  • 增加了程序的复杂度。需要面向抽象层编程。

使用的场景

实现系统可能有多个角度分类维度,每一种角度维度都可能变化。
把这种多角度多维度分类分离出来,让它们独立变化,减少它们之间耦合

如何理解桥接模式 【重要】

理解桥接模式,就是理解多维度概念,理解多维度最好的参照物就是坐标系。

多维度的概念

坐标系就是多维度的体现。我们说的二维,三维就是维度的概念。

二维空间种,(x,y)代表一个坐标点。函数如下。x轴代表横向维度,y轴代表纵向维度。两个维度互不影响。每个维度的移动都和其他维度无影响。比如 x 向左向右,和y 维度不同互不相关。

当我们把 x轴,y轴按照 垂直角度相交,并 通过函数 桥接在一起时。 两个维度组成了坐标系空间。
y = F ( x ) y=F(x) y=F(x)
在坐标系统种,有无数的点。通过y=F(x)进行标识。F(x)的具体实现有很多种不同的函数,有三角函数,指数函数很多函数。这些函数就是我们 y轴对 x轴的 抽象扩展。那么x本身的具体实现是什么,是函数偏移。x=f(dx * 2 ) , x = f(dx + 1) ,其中dx *2 , dx + 1 就是x轴的具体偏移实现。
x = f ( d x ) : d x + 1 , d x ∗ 2 , d x 2 . . . . x=f(dx) : dx + 1 , dx * 2 , dx^2.... x=f(dx)dx+1,dx2,dx2....

y = F ( x ) = [ x 2 + 2 a b + 1 , k x , s i n ( x ) . . . ] y =F(x) =[x^2+2ab+1 , kx, sin(x)... ] y=F(x)=[x2+2ab+1,kx,sin(x)...]
提供给外部使用的桥接方法获取信息。
( x , y ) = F ( x ) = F ( f ( d x ) ) (x,y)=F(x)=F(f(dx)) x,y)=F(x)=F(f(dx))

如果把 y = F(x) 当成桥接类。表示 x的点 通过 某种 函数,桥接到 y 上。那么 抽象化的y 和 实现化的 x就解耦了。因为 x的变化扩展,通过f(dx)接口定义。y的变化,通过 F(x)的接口定义。

通过两个维度的(f(dx), F(x)) 就可以定义出我们需要的一个坐标点求解路径【客户端通过该【求解路径】求出坐标点】。

求解路径:二维空间提供给用户的一个场景【用户真正需要的东西】。

( x , y ) = ( x , F ( x ) ) = ( f ( d x ) , F ( f ( d x ) ) ) (x,y) = (x,F(x)) = (f(dx), F(f(dx))) x,y)=(x,F(x))=(f(dx),F(f(dx)))
即 dx = 10
F ( x ) = 2 ∗ x = 2 ∗ f ( d x ) = 2 ∗ ( 2 ∗ 10 ) = 40 F(x)=2*x=2*f(dx)=2*(2*10)=40 F(x)=2x=2f(dx)=2(210)=40

对于 用户(学生)使用坐标系空间求解。只需要输入一个 dx,即可完成 坐标点的求解(f(dx),F(x)).

如果 x = f(dx)=dx+1 , y=F(x)= 2x ,那么我们在 dx = 1 【客户端调用坐标点方法的入参】的时候,得到的实际结果是 (x=f(1)=1+1,y=F(f(1))=F(2)=2*2)=(2,4)

以下是桥接模式的几个关键角色:
  • 抽象(Abstraction):定义抽象接口,通常包含对实现接口的引用。
  • 扩展抽象(Refined Abstraction):对抽象的扩展,可以是抽象类的子类或具体-实现类。
  • 实现(Implementor):定义实现接口,提供基本操作的接口。
  • 具体实现(Concrete Implementor):实现实现接口的具体类。

对应坐标系后:

抽象: F(x)
扩展抽象: Y1=F(x)=2x^2, Y2=F(x)=2x, Y3=F(x)=sin(x) 。
实现: f(dx)
具体实现: X1=f(dx)=2dx , X2=f(dx) = 1/dx

客户端需要的是:

int x = 10;
// x维度独立
f(x) a = new X1();
a.get(x) = 20 ; 

// y维度独立
// y的可以扩展自己的函数子类。和 x具体类无关。
F(x) bridge = new Y1(new X1());
(x,y)=bridge.call(10);
// (2,8)

// 新增一个类 Y4=logx实现。
F(x) logx=new Y4(new X1());
// Y4不会影响X1,X1也不会影响到Y4.
所以 F(x) 和 f(dx) 单独独立发展各自的扩展。
并桥接在一起提供复杂能力。

实现

举例:

在一个商品空间内。我们如果需要获取一个具体的坐标商品。需要根据我们商品空间内维度的定义。

假设:商品空间由 (折扣,售价区间)组成一个坐标空间(x,y).

折扣维度上我们分了: 5折 , 不打折

售价空间维度:1000以下,1000~5000,5000以上

那么一个商品空间的所有坐标点个数: 2 x 3 = 6 个坐标。即6种实现。

	这里映射到二维空间种:
	
	x=f(dx) : 售价空间 : 抽象售价空间接口
	
	y=f(x) : 折扣抽象桥接类
	
	x=f(dx)  : dx - 1:--> 类比 1000元以下
	
	x=f(dx) : dx+ 2 : --> 类比 1000~5000
	
	x=f(dx)  : dx + 3 : -->类比  5000+
	
	y具体函数:y=f(x) : x*0.5 :   -->   类比   5折
	
	y具体函数:y=f(x) : x * 1.0 : --> 类比  不打折

传统方法【类爆炸】非桥接模式

通过类继承来实现多维度功能

实现难度: ⭐️ ⭐️

在传统开发中。我们如何实现呢。抽象出两个接口 折扣接口和售价空间接口

我需要一个 5折的售价空间1000以下的商品。那么就需要定义一个类先继承5折折扣,在继承1000以下售价空间。

java中只有单继承,所以就会形成链式继承。当维度增加时。实现一个坐标点类,就会无限延长。导致类爆炸的情形

使用正常类继承方式创建实际商品类。

public interface 折扣 {}

public interface 区间 {}

public class 5折 extends 折扣{}
public class 不打折 extends 折扣 {}

public class 1000以下 extends 区间{}
public class 1000~5000 extends 区间{}
public class 5000以上 extends 区间{}

public class 5折苹果 实现 5折 {}
public class 5折+1000以下苹果 extends 5折苹果 实现 1000以下 {}
... 

如果 折扣新增一个 1折 折扣呢,新增类又要新增 许多了。

所以当多个维度同时变化的时候,对于一个具体实现多个维度的子类来说。变化是 以 另外维度的乘积数。

如何解决。这里就是用到了桥接模式。

在多维度中。我们不希望,一个维度的扩展,导致实现类的爆炸性编码类的产生。

桥接模式

难度: ⭐️ ⭐️ ⭐️ ⭐️ ⭐️
请添加图片描述
样例代码: 二维坐标例子

https://gitcode.net/k316378085/Java/-/tree/master/java/com/kongxiang/raindrop/dp/type/structure/bridge/twodimensional
客户端使用:

public static void main(String[] args) {
        // 学生练习题
        // 创建试卷练习题
        //试题: 偏移函数 dx+1 ,y函数 x*2 ,当给定x轴上的点是8的时候,求空间上的点
        Y exercise = new Y2x(new XAdd1());
        // 学生回答
        answerQuest(exercise);
        exercise = new Y2x(new XMov2());
        answerQuest(exercise);
        exercise = new Ylog(new XMov2());
        answerQuest(exercise);
        exercise = new Ylog(new XAdd1());
        answerQuest(exercise);
        // 假设 x 有 m种扩展算法, y种有n种算法
        // 现在将2维拓展到3维,新增一个维度的化,每增加一个三维z的抽象实例
        // 就可以新增 m*n 的不同算法题。
        // 如果z 有 o 种算法。那么 在三维空间种的算法表达就有 m * n * o 种 具体算法题。
        //Z exercise = new Zlog(new Ylog(new XAdd1()));
}

 private static void answerQuest(Y exercise) {
        Point fxResult = exercise.getFxResult(8);
        System.out.println("x " + fxResult.getX() + " : Y " + fxResult.getY());
    }

在这里插入图片描述

总结

  1. 在扩展维度时,只需要要将 当前的 Abstraction 作为 Implementor 层。新增的维度作为Abstraction。去扩展即可。可以满足无线拓展的需求。对之前的维度没有任何影响。
  2. 区分多维度,如果需要多维度不相关的独立扩展。那么我们就应该使用桥接模式。通过这种结构组合方式,达到无限扩展的需求。

订单优惠的维度:
1. 优惠卷种类
2. 地区
3. 渠道
4. 砍一刀:人数区间
5. 购物节

动物的速度模型的维度:
1. 科目:狗科:基准2 驴科:基准0.8
2. 体重范围
3. 流线型分数
4. 海洋或陆地

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嘉羽很烦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值