桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。
问题:
这里的抽象与实现是什么意思呢?先来看一个例子:
假如你有一个几何形状Shape类,从它能扩展出两个子类: 圆形Circle和 方形Square 。 你希望对这样的类层次结构进行扩展以使其包含颜色,所以你打算创建名为红色Red和蓝色Blue的形状子类。 但是, 由于你已有两个子类, 所以总共需要创建四个类才能覆盖所有组合, 例如 蓝色圆形BlueCircle和 红色方形RedSquare 。
在层次结构中新增形状和颜色将导致代码复杂程度指数增长。 例如添加三角形状, 你需要新增两个子类, 也就是每种颜色一个; 此后新增一种新颜色需要新增三个子类, 即每种形状一个。 照这样下去,所有组合类的数量将以几何级数增长,情况会越来越糟糕。
解决方案:
问题的根本原因在于我们试图在两个独立的维度——形状与颜色上进行扩展。这在处理继承时是很常见的问题。
桥接模式 通过将继承改为组合的方式来解决这个问题。 具体来说, 就是抽取其中一个维度并使之成为独立的类层次, 这样就可以在初始类中引用这个新层次的对象, 从而使得一个类不必拥有所有的状态和行为。
根据该方法, 我们可以将颜色相关的代码抽取到拥有 红色和 蓝色两个子类的颜色类中, 然后在 形状类中添加一个指向某一颜色对象的引用成员变量。 现在, 形状类可以将所有与颜色相关的工作委派给连入的颜色对象。 这样的引用就成为了 形状和 颜色之间的桥梁。 此后, 新增颜色将不再需要修改形状的类层次, 反之亦然。
我们就以上述形状与颜色这两个独立的维度来实现给不同的形状刷上不同颜色的例子来讲解:
ColorAPI :用于画各种颜色的接口
/**
* Created on 2020/3/18
* Package com.design_pattern.bridge
*
* @author dsy
*/
public interface ColorAPI {
public void paint();
}
BlueColorAPI :画蓝色的实现类
/**
* Created on 2020/3/18
* Package com.design_pattern.bridge
*
* @author dsy
*/
public class BlueColorAPI implements ColorAPI {
@Override
public void paint() {
System.out.println("画上蓝色");
}
}
RedColorAPI :画红色的实现类
/**
* Created on 2020/3/18
* Package com.design_pattern.bridge
*
* @author dsy
*/
public class RedColorAPI implements ColorAPI
{
@Override
public void paint() {
System.out.println("画上红色");
}
}
Shape :抽象形状类
/**
* Created on 2020/3/18
* Package com.design_pattern.bridge
*
* @author dsy
*/
public abstract class Shape {
protected ColorAPI colorAPI; //添加一个颜色的成员变量以调用ColorAPI 的方法来实现给不同的形状上色
public void setDrawAPI(ColorAPI colorAPI) { //注入颜色成员变量
this.colorAPI= colorAPI;
}
public abstract void draw();
}
Circle :圆形类
/**
* Created on 2020/3/18
* Package com.design_pattern.bridge
*
* @author dsy
*/
public class Circle extends Shape {
@Override
public void draw() {
System.out.print("我是圆形");
colorAPI.paint();
}
}
Rectangle :长方形类
/**
* Created on 2020/3/18
* Package com.design_pattern.bridge
*
* @author dsy
*/
public class Rectangle extends Shape {
@Override
public void draw() {
System.out.print("我是长方形");
colorAPI.paint();
}
}
Client:客户端
/**
* Created on 2020/3/18
* Package com.design_pattern.bridge
*
* @author dsy
*/
public class Client {
public static void main(String[] args) {
//创建一个圆形
Shape shape = new Circle();
//给圆形蓝色的颜料
shape.setDrawAPI(new BlueColorAPI());
//上色
shape.draw();
//创建一个长方形
Shape shape1 = new Rectangle();
//给长方形红色的颜料
shape1.setDrawAPI(new RedColorAPI());
//上色
shape1.draw();
}
}
打印输出:
我是圆形画上蓝色
我是长方形画上红色
假如现在客户让我们增了一个三角形,我们只需要新增一个三角形类就可以了,而无需把每一种颜色都增加一个,我们在客户端调用时只需按照需求来挑选即可:
/**
* Created on 2020/3/18
* Package com.design_pattern.bridge
*
* @author dsy
*/
public class Triangle extends Shape {
@Override
public void draw() {
System.out.println("我是三角形");
colorAPI.paint();
}
}
增加颜色也是一样,我们只需要增加一个新的颜色并实现ColorAPI的接口即可,而无需更改类的层次,例如增加一个绿色:
/**
* Created on 2020/3/18
* Package com.design_pattern.bridge
*
* @author dsy
*/
public class GreenColorAPI implements ColorAPI {
@Override
public void paint() {
System.out.println("画上绿色");
}
}
现在再来看“将抽象部分与他的实现部分分离”这句话,实际上就是在说实现系统可能有多个角度分类(例如例子中的形状与颜色),每一种分类都有可能变化,那么把这种多角度分离出来让他们独立变化,减少他们之间的耦合。
优点:
缺点: