桥梁模式是对象的结构模式。又称为柄体(Handle and Body)模式或接口(Interface)模式。桥梁模式的用意是“将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化”。
我们假设一个场景:我们需销售电脑,电脑有三种:台式电脑,笔记本电脑,平板电脑。每种电脑又有多个品牌:联想,戴尔等等。。
所以我们需要写如下代码:
1 package top.bigking.bridge; 2 3 import sun.security.krb5.internal.crypto.Des; 4 5 /** 6 * @Author ABKing 7 * @Date 2020/2/15 下午11:03 8 **/ 9 public interface Computer1 { 10 void sale(); 11 } 12 class Desktop implements Computer1{ 13 @Override 14 public void sale() { 15 System.out.println("销售台式电脑"); 16 } 17 } 18 class Laptop implements Computer1{ 19 @Override 20 public void sale() { 21 System.out.println("销售笔记本电脑"); 22 } 23 } 24 class Pad implements Computer1{ 25 @Override 26 public void sale() { 27 System.out.println("销售平板电脑"); 28 } 29 } 30 class LenovoDesktop extends Desktop{ 31 @Override 32 public void sale() { 33 System.out.println("销售联想台式电脑"); 34 } 35 } 36 class LenovoLaptop extends Laptop{ 37 @Override 38 public void sale() { 39 System.out.println("销售联想笔记本电脑"); 40 } 41 } 42 class LenovoPad extends Pad{ 43 @Override 44 public void sale() { 45 System.out.println("销售联想平板电脑"); 46 } 47 }
这样就不可避免地带来一个问题,当需要扩展新的品牌,新的电脑类型时,维护会变得非常困难,需要增加相当多的类。
究其原因,是因为一个类同时被两个因素制约:种类 和 品牌。
为了消除这个耦合,我们引入了桥接模式,把一个因素变成类的属性。
写一个Computer2类
1 package top.bigking.bridge; 2 3 /** 4 * @Author ABKing 5 * @Date 2020/2/15 下午11:26 6 **/ 7 public abstract class Computer2 { 8 protected Brand brand; 9 public Computer2(Brand brand) { 10 this.brand = brand; 11 } 12 public void sale(){ 13 brand.sale(); 14 } 15 } 16 class Desktop2 extends Computer2 { 17 public Desktop2(Brand brand) { 18 super(brand); 19 } 20 @Override 21 public void sale() { 22 super.sale(); 23 System.out.println("销售台式机电脑"); 24 } 25 } 26 class Laptop2 extends Computer2{ 27 public Laptop2(Brand brand) { 28 super(brand); 29 } 30 @Override 31 public void sale() { 32 super.sale(); 33 System.out.println("销售笔记本电脑"); 34 } 35 }
还需要一个制约品牌的因素
1 package top.bigking.bridge; 2 3 /** 4 * @Author ABKing 5 * @Date 2020/2/15 下午11:27 6 **/ 7 public interface Brand { 8 void sale(); 9 } 10 class Lenovo implements Brand{ 11 @Override 12 public void sale() { 13 System.out.println("品牌为联想"); 14 } 15 } 16 class Dell implements Brand{ 17 @Override 18 public void sale() { 19 System.out.println("品牌为戴尔"); 20 } 21 }
运行JUnit单元测试:
1 package top.bigking.bridge; 2 3 import org.junit.Test; 4 5 /** 6 * @Author ABKing 7 * @Date 2020/2/15 下午11:38 8 **/ 9 public class TestBridge { 10 @Test 11 public void testBridge(){ 12 Brand brand = new Lenovo(); 13 Computer2 c = new Desktop2(brand); 14 c.sale(); 15 } 16 }
运行结果:
品牌为联想
销售台式机电脑
桥接模式总结:
- 桥接模式可以取代多层继承的方案。多层集成违背了单一职责原则,复用性较差,类的个数也非常多。桥接模式可以极大地减少子类的个数,从而降低管理和维护的成本。
- 桥接模式极大地提高了系统可扩展性,在两个变化维度中任意扩展一个维度,都不需要修改原有的系统,符合开闭原则。
桥接模式在开发应用中的场景:
JDBC驱动程序
AWT中的Peer结构
银行日志管理:
格式分类:操作日志、交易日志、异常日志
距离分类:本地记录日志、异地记录日志
人力资源系统中的奖金计算模块
奖金分类:个人奖金、团体奖金、激励奖金
部门分类:人事部门、销售部门、研发部门
OA系统中的消息处理
业务类型:普通消息、加急消息、特急消息
发送消息方式:系统内消息、手机短信、邮件