设计模式之桥接模式

桥接模式

1.基本介绍

  • 桥接模式(Bridge)是指将实现与抽象放在两个不同的类层次中,是两个层次可以独立改变
  • 该模式基于类的最小设计原则(扩展功能时尽量少的增加类),通过使用封装、聚合、继承等行为让不同的类承担不同的职责
  • 主要特点是把抽象和行为实现分离开来,从而可以保持各部分的独立性以及对他们的功能扩展

2.原理类图

  • client:桥接模式的调用者
  • 抽象类(Abstraction):维护了Implementor即他的实现类,二者是聚合关系,Abstraction充当桥接类
  • RefinedAbstraction:是Abstraction的子类
  • Implementor是行为实现类的接口

从UML图看,这里的抽象类和接口是聚合关系,就是调用和被调用的关系;RefinedAbstraction的父类聚合了接口,RefinedAbstraction调用接口的具体实现

3.示例说明

  1. 如图:由于手机品牌以及样式的不同,每个手机的功能使用方式不相同,使用传统的继承方法,可以发现,每当我们扩展要增加一个新的品牌或者新的样式时,都要添加n个类,特别的繁琐,不易于开发

  1. 使用桥接模式对以上结构进行优化
    • 如图,抽象类Phone聚合了品牌接口Brand,Phone的子类即手机样式与品牌分隔开,选择一个手机样式,选择一个品牌,然后将其在Phone中进行组合,得到想要产品,Phone则是充当桥梁的作用
    • 创建手机对象时,先选择手机样式,调用其父类聚合的Brand接口来获取指定的手机品牌,而phone中的call操作则是直接调用brand中的call,以达到我们想要的效果
    • 如此扩展的时候,也不要添加很多的类,当你想要新增一个品牌,只需要在Brand多实现一个类即可,新增样式也只需要在phone下继承一个子类

  1. 代码示例

    1. 定义Brand接口以及各个品牌的具体实现

      //定义接口
      public interface Brand {
      	public void call();
      }
      //Vivo实现
      class Vivo implements Brand{
      	@Override
      	public void call() {
      		// TODO Auto-generated method stub
      		System.out.println("Vivo 开机");
      	}
      	
      }
      //HuaWei实现
      class HuaWei implements Brand{
      	@Override
      	public void call() {
      		// TODO Auto-generated method stub
      		System.out.println("HuaWei 开机");
      	}
      }
      //XiaoMI实现
      class XiaoMI implements Brand{
      	@Override
      	public void call() {
      		// TODO Auto-generated method stub
      		System.out.println("XiaoMI 开机");
      	}
      }
      
    2. 编写桥梁类即抽象类Phone

      public abstract class Phone {
      	//聚合Brand接口
      	private Brand brand;
      	//构造器:被子类调用
      	public Phone(Brand brand) {
      		this.brand = brand;
      	}
      	//定义手机功能,调用品牌的具体实现
          //注意该方法应该定义为protected,因为该方法还没有完成,还需要子类的填充,所以不能被调用
      	protected void call() {
      		brand.call();
      	}
      }
      
    3. 举例一个继承Phone的子类Folder样式手机

      public class FolderPhone  extends Phone{
      	//调用父类构造器,完成品牌手机的聚合
      	public FolderPhone(Brand brand) {
      		super(brand);
      	}
      	//重写父类的call,调用父类的call方法,即保留品牌手机的操作,再加上样式的特点,完成手机的功能实现
      	public void call() {
      		super.call();
      		System.out.println("添加了折叠手机的特色");
      	}
      }
      
    4. 而client调用时,只需要指定类型创建

      //指定折叠手机中的vivo品牌,便完成一个完整的手机
      Phone phone = new FolderPhone(new Vivo());
      

    以上则通过桥接模式完成一个手机功能,整个系统具有扩展性

4.JDBC中的桥接模式

JDBC在使用Driver获取Connection中使用了桥接模式,但是和我们所说的结构有所不同,DriverManager不是一个抽象,但他使用的桥接模式的大致结构。

5.小结

  • 对于系统的高层来说,只需要知道抽象部分和实现部分的接口就够了,其他部分由具体业务来完成
  • 桥接模式代替多层继承方案,可以减少子类的个数,降低系统的管理和维护成本
  • 桥接模式要求正确识别出系统中的两个独立变化维度,因此其使用范围有一定的局限性,适用于一定的应用场景

6.应用场景

  • 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式犹为适用
  • 常用的场景:
    • JDBC驱动程序
    • 银行转账系统
      • 转账分类:网上转账、柜台转账、ATM转账
      • 用户类型:普通用户、银卡用户、金卡用户
    • 消息管理
      • 消息类型:即时消息、延时消息
      • 消息分类:手机短信、邮件信息、QQ消息
原文地址:https://www.cnblogs.com/JIATCODE/p/13068225.html