介绍
桥接(Bridge)模式的定义如下:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
桥接模式适合处理一个类有多个维度的属性,并且多个维度都可能独立的发生变化。如果只看定义很难去理解桥接模式的含义。下面通过示例来更好的介绍桥接模式
案例
在生活中我们可以接触到奶茶,如果点过奶茶就会发现,奶茶具有多项可以自定义的属性,比如种类,容量,小料,温度等等。如果我们为每一个不同的奶茶都建立一个类,那么这个类的数量将是乘积增加的。
为了解决这种一个物品有多维度的属性的问题,提出了桥接模式的方法,我们将每个维度中的每个属性都是为一个类,例如容量有大中小,我们就认为容量有三个类。然后通过每个维度属性类的相互组合来完成一杯完整属性奶茶的构建。这样可以将类的数量由原本的乘积增加改成加法增加,大幅减少类的数量。
桥接模式结构
桥接模式主要分为以下四个角色
抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化对象的引用。
扩展抽象化(RefinedAbstraction)角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。
具体实现化(ConcreteImplementor)角色:给出实现化角色接口的具体实现。
直接看有点费劲,还是举奶茶的例子来说,假如我们将种类视为奶茶的主维度属性,其他容量和小料作为可组合的维度属性。那么奶茶类则是抽象化角色,然后各种种类的奶茶继承奶茶类,则为扩展抽象化角色。实现化角色则定义了奶茶添加其他维度属性的接口。具体实现化角色则会具体实现接口内容。
代码实现
抽象化角色
@Data
public abstract class MilkyTea {
//需要在抽象化角色中引入实现化角色,这是组合的关键
Capacity capacity;
Condiments condiments;
public MilkyTea(){
}
//通过有参构造来接受具体的组合内容
public MilkyTea(Capacity capacity,Condiments condiments)
{
this.capacity=capacity;
this.condiments=condiments;
}
//制作奶茶,具体交由修正抽象类实现
public abstract void make();
}
修正抽象化角色
//修正抽象,杨枝甘露
@Data
public class Mango extends MilkyTea {
public Mango(Capacity capacity,Condiments condiments)
{
super(capacity,condiments);
}
@Override
public void make() {
capacity.chooseCapacity();
condiments.add();
System.out.println("制作杨枝甘露");
}
}
修正抽象化角色中需要实现抽象化角色方法
实现化角色
容量类
public interface Capacity {
//选择容量
public void chooseCapacity();
}
小料类
public interface Condiments {
public void add() ;
}
具体实现化角色
大容量
public class BigCapacity implements Capacity{
@Override
public void chooseCapacity() {
System.out.println("大杯");
}
}
小容量
public class SmallCapacity implements Capacity{
@Override
public void chooseCapacity() {
System.out.println("小杯");
}
}
小料添加珍珠
public class SmallCapacity implements Capacity{
@Override
public void chooseCapacity() {
System.out.println("小杯");
}
}
小料添加芋泥
public class Taro implements Condiments{
@Override
public void add() {
System.out.println("添加芋泥");
}
}
测试
@Test
public void Bridge()
{
MilkyTea milkyTea=new Mango(new BigCapacity(),new Pearl());
milkyTea.make();
}
测试结果
大杯
添加珍珠
制作杨枝甘露
总结
由上面例子可以看出来,桥接模式更加适合一种物品有多维度属性,通过桥接模式将多维度属性通过组合的方式添加,避免类数量爆炸的问题,同时也实现了抽象与实现的分离。
但是这种方法的缺点也是很明显的,随着类的数量增多,关系会相对继承显得更加错综复杂。