十、桥接设计模式
10.1 桥接设计模式简介
10.1.1 桥接设计模式概述
桥接模式(Bridge Pattern):将抽象部分与实现部分分离,使得它们可以独立变化。
Tips:需要注意的是,桥接模式中的抽象并不是指抽象类或接口这种硬性概念,实现也不是具体指实现类;抽象与实现分离指的是两种维度的分离。这需要我们继续学习后面的知识;
桥接模式主要的目的就是用组合/聚合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
【案例】
我们需要创建不同品牌的不同设备,这种关系使用继承来描述如下:
设计好继承体系后,我们发现类的数量非常非常多,如果需要新增一个品牌或者新增一个设备都会导致类的数量激增;因为一个品牌都有手机、电脑、相机等设备。一个设备也会有小米、华为、神舟等品牌;这样一来不利于后期的维护。
- 在上述案例中,可将系统划分为两个纬度:
所谓抽象与实现的分离指的是:不直接编写小米手机类、小米电脑类去继承小米这个品牌。而是将系统分为两个纬度(品牌、设备)一个为抽象纬度(品牌),一个为实现纬度(设备)进行抽象化;这样抽象与实现就进行分离了。
10.1.2 桥接设计模式的UML类图
桥接模式中,主要包含4个角色:
- 1)抽象角色(Abstraction):确定抽象纬度的产品基本操作,该类持有一个对具体实现角色的引用,其构造函数规定子类需要传递一个具体的实现对象,抽象角色是桥接模式用于组合的关键;
- 2)具体抽象角色(Refined Abstraction):Abstraction的具体实现,对Abstraction的方法进行实现;
- 3)实现角色(Implementor):确定实现纬度的产品基本操作,提供给Abstraction使用;
- 4)具体实现角色(Concrete Implementor):Implementor的具体实现;
10.2 桥接模式的实现
桥接模式将系统体系划分为了多个纬度来看待;多个纬度采用组合的方式来进行代码的解耦;
我们将产品作为实现纬度,品牌作为抽象纬度来设计系统的体系;
- 抽象角色-产品:
package com.dfbz.demo01;
/**
* @author lscl
* @version 1.0
* @intro: 抽象角色
*/
public abstract class Product {
// 使用组合关系关联产品的品牌(包含具体实现角色的引用)
protected Brand brand;
public Product(Brand brand) {
this.brand = brand;
}
public abstract String getProduct();
public void show() {
System.out.println("您正在使用【" + brand.getBrand() + "】牌【" + getProduct() + "】");
}
}
- 具体抽象角色1-手机产品:
package com.dfbz.demo01;
/**
* @author lscl
* @version 1.0
* @intro: 具体抽象角色
*/
public class PhoneProduct extends Product {
public PhoneProduct(Brand brand) {
super(brand);
}
@Override
public String getProduct() {
return "手机";
}
}
- 具体抽象角色2-电脑产品:
package com.dfbz.demo01;
/**
* @author lscl
* @version 1.0
* @intro: 具体实现角色
*/
public class ComputerProduct extends Product {
public ComputerProduct(Brand brand) {
super(brand);
}
@Override
public String getProduct() {
return "电脑";
}
}
- 实现角色-品牌:
package com.dfbz.demo01;
/**
* @author lscl
* @version 1.0
* @intro: 实现角色
*/
public interface Brand {
String getBrand();
}
- 具体实现角色1-小米品牌:
package com.dfbz.demo01;
/**
* @author lscl
* @version 1.0
* @intro: 具体实现角色
*/
public class XiaoMiBrand implements Brand {
@Override
public String getBrand() {
return "小米";
}
}
- 具体实现角色2-华为品牌:
package com.dfbz.demo01;
/**
* @author lscl
* @version 1.0
* @intro: 具体实现角色
*/
public class HuaWeiBrand implements Brand {
@Override
public String getBrand() {
return "华为";
}
}
- 测试类:
package com.dfbz.demo01;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo01 {
public static void main(String[] args) {
Brand brand = new XiaoMiBrand();
Product product = new ComputerProduct(brand);
product.show(); // 小米牌电脑
System.out.println("------------------");
brand = new HuaWeiBrand();
product = new PhoneProduct(brand);
product.show(); // 华为牌手机
System.out.println("------------------");
product = new ComputerProduct(brand);
product.show(); // 华为牌电脑
System.out.println("------------------");
}
}
运行效果如下:
10.3 桥接模式的优缺点
-
优点:
- 1)通过利用组合/聚合的关系来代替继承关系,提高了系统的扩展性,可维护性
- 2)符合开闭原则
- 3)符合合成复用原则
-
缺点:
- 1)需要用户正确识别系统中两个独立的纬度变化,提高了系统的复杂性