[设计模式/Java] 设计模式之桥接模式【17】
序
- 大学阶段,已在专业课程中系统学习过设计模式。
- 但随着进入企业工作,对设计模式的理解才愈加深刻,为此有必要对设计模式进行专门的总结、提炼,以指导未来的程序设计与开发工作。
- 本文主要参考自:
概述:桥接模式
模式定义
- 桥接模式(Bridge Pattern):将抽象部分与它的实现部分【分离】,使它们都可以独立地变化。
- 属于结构型设计模式
模式解释
- 这里的抽象与实现是什么意思呢?
先来看一个例子:
- 假如你有一个几何形状
Shape类,从它能扩展出2个子类: 圆形Circle和方形Square。- 你希望对这样的类层次结构进行扩展以使其包含颜色,所以你打算创建名为红色Red和蓝色Blue的形状子类。
- 但是, 由于你已有2个子类, 所以总共需要创建4个类才能覆盖所有组合
例如 蓝色圆形Blue Circle和 红色方形Red Square 。

- 在层次结构中新增形状和颜色将导致代码复杂程度呈指数增长。
例如: 添加三角形状, 你需要新增两个子类, 也就是每种颜色一个;
此后新增一种新颜色需要新增三个子类, 即每种形状一个。
照这样下去,所有组合类的数量将以几何级数增长,情况会越来越糟糕。
- 解决方案:
- 问题的根本原因在于我们试图在两个独立的维度——形状与颜色上进行扩展。
这在处理继承关系时是很常见的问题。
- 桥接模式:通过将继承改为组合的方式来解决这个问题。
具体来说, 就是抽取其中一个维度并使之成为独立的类层次, 这样就可以在初始类中引用这个新层次的对象, 从而使得一个类不必拥有所有的状态和行为。

- 根据该方法, 我们可以:
- 将颜色相关的代码抽取到拥有 红色和 蓝色两个子类的颜色类中
- 然后在形状类中添加一个指向某一颜色对象的引用成员变量。
- 现在,形状类可以将所有与颜色相关的工作【委派】给连入的颜色对象。
- 这样的引用就成为了形状和颜色之间的桥梁。
此后, 新增颜色将不再需要修改形状类的类层次, 反之亦然。
模式的组成

- 
Abstraction(抽象类):用于定义抽象类的接口,它一般是抽象类而不是接口,其中定义了一个Implementor(实现类接口)类型的对象并可以维护该对象,它与Implementor之间具有关联关系。
- 
RefinedAbstraction(提炼抽象类):扩充由Abstraction定义的接口,通常情况下它不再是抽象类而是具体类,它实现了在Abstraction中声明的抽象业务方法,在RefinedAbstraction中可以调用在Implementor中定义的业务方法。
- 
Implementor(实现类接口):定义实现类的接口,这个接口不一定要与 `Abstraction 的接口完全一致,事实上这两个接口可以完全不同,一般而言,Implementor 接口仅提供基本操作,而 Abstraction 定义的接口可能会做更多更复杂的操作。
Implementor 接口对这些基本操作进行了声明,而具体实现交给其子类。
通过关联关系,在 Abstraction 中不仅拥有自己的方法,还可以调用到 Implementor 中定义的方法,使用关联关系来替代继承关系。
- ConcreteImplementor(具体实现类):具体实现- Implementor接口,在不同的- ConcreteImplementor中提供基本操作的不同实现,在程序运行时,- ConcreteImplementor对象将替换其父类对象,提供给抽象类具体的业务操作方法。
适用场景
- 
一个类存在两个及以上独立变化的维度,且这多个维度都需要进行扩展。 
- 
如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。 
- 
对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。 
设计模式的原则之一: 少继承,多聚合(组合)。
模式特点
优点
- 
实现抽象和实现的分离 
- 
桥接模式提高了系统的可扩展性,在两个或更多变化维度中任意扩展一个维度,都不需要修改原有系统 
- 
桥接模式有时类似于多继承方案,但是多继承方案违背了类的单一职责原则 
- 即一个类只有一个变化的原因
因此,多继承结构的方案,复用性比较差
- 且多继承结构中类的个数非常庞大。
- 桥接模式是比多继承方案更好的解决方法
缺点
- 
桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。 
- 
桥接模式要求正确识别出系统中两个独立变化的维度 
因此,其使用范围具有一定的局限性。
案例实践
CASE: Shape(几何形状) 与 Color(颜色)
我们就以上述的形状与颜色案例中,这两个独立的维度来实现给不同的形状刷上不同颜色的例子来讲解:
ICorlor / BlueColor / RedColor
- IColor :用于画各种颜色的颜色接口
public interface IColor {
    public void paint();
}
- BlueColor :画蓝色的颜色接口实现类
public class BlueColor implements IColor {
    @Override
    public void paint() {
        System.out.println("画上蓝色");
    }
}
- RedColor :画红色的颜色接口实现类
public class RedColor implements IColor {
    @Override
    public void paint() {
        System.out.println("画上红色");
    }
}
AbstractShape / Circle / Rectangle
- AbstractShape : 形状接口
public abstract class AbstractShape {
    protected IColor color;  //添加一个颜色的成员变量以调用 IColor 的方法来实现给不同的形状上色
    public void setDraw(IColor color) {      //注入颜色成员变量
        this.color= color;
    }
 
    public abstract void draw();        
}
- Circle : 圆形
public class Circle extends AbstractShape {
    @Override
    public void draw() {
        System.out.print("我是圆形");
        color.paint();
    }
}
- Rectangle : 长方形
public class Rectangle extends AbstractShape {
    @Override
    public void draw() {
        System.out.print("我是长方形");
        color.paint();
    }
}
Client
public class Client {
    public static void main(String[] args) {
        //创建一个圆形
        AbstractShape shape = new Circle();
        //给圆形蓝色的颜料
        shape.setDraw(new BlueColor());
        //上色
        shape.draw();
        //创建一个长方形
        AbstractShape shape1 = new Rectangle();
        //给长方形红色的颜料
        shape1.setDraw(new RedColor());
        //上色
        shape1.draw();
    }
}
out
我是圆形画 上蓝色
我是长方形 画上红色
需求扩展:增加三角形形状
- 假如现在客户让我们增了一个三角形,我们只需要新增一个三角形类就可以了,而无需把每一种颜色都增加一个。
我们在客户端调用时只需按照需求来挑选即可:
public class Triangle extends AbstractShape {
    @Override
    public void draw() {
        System.out.println("我是三角形");
        color.paint();
    }
}
需求扩展:增加黄颜色
- 增加颜色也是一样,我们只需要增加一个新的颜色并实现IColor的接口即可,而无需更改类的层次
例如,增加一个黄色:
public class YellowColor implements IColor {
    @Override
    public void paint() {
        System.out.println("画上绿色");
    }
}
小结
- 现在再来看“将抽象部分与他的实现部分分离”这句话,实际上就是在说:
实现系统可能有多个角度分类(例如例子中的形状与颜色),每一种分类都有可能变化,那么把这种多角度分离出来让他们独立变化,减少他们之间的耦合。
CASE : 计算机网络中的桥接模式
- 计算机网络设备的网络模式:
- 路由器模式

- 桥接模式

- ...
- 相关联系
- VmWare提供了3种网络工作模式
- Bridged(桥接模式) - VMnet0
- NAT(网络地址转换模式) - VMnet8
- Host-Only(仅主机模式)- VMnet1



那根虚拟网桥,像不像上面说的【引用对象(color)】
- 推荐文献
docker有4种网络模式: host模式 / container模式 / none模式 / bridge模式
`VmWare`提供了3种网络工作模式
1 Bridged(桥接模式) - VMnet0
2 NAT(网络地址转换模式) - VMnet8
3 Host-Only(仅主机模式)- VMnet1
Y 推荐文献
X 参考文献
 
    本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号