桥接模式(Bridge Pattern)

模式动机:
    开发一个程序,可以绘制矩形、正方形、圆形、椭圆形四种图形,且每个图形都有不同的颜色如:红、绿、蓝。
    最直接的作法是: 为每一种图形都提供一种颜色的类, 示意图如下:会发现完成该类图需要4*3=12个类,如果再多几种图形或是多几种颜色,会发现有非常多的子类。
 
 
    现在面临的问题是子类太多,而且随着图形和颜色的增加,子类会越来越多,如果再添加一个维度:人,不同的人(如:成年男性、成年女性和小孩等)可以绘制多种不同颜色的图形,那子类将达到:3种人*4种图形*3种颜色=36个。
    分析以上问题发现有图形和颜色两个维度都在变化,最终的输出结果是两个维度的组合,所以可以采用以下的方式来设计:
    从类图中可以看到图形和颜色有各自的互不干扰的独立继承体系,这样的优点在于图形或是颜色遇到变化(拥抱变化设计)而扩展(对扩展开放,这里的通过继承来扩展)时可以不影响对方,且子类的数量大大减少。这种设计方式称之为桥接方式:对于有 两个变化维度(也可以是多个)的系统,采用上述设计系统中的 类的个数更少,系统也 更宜扩展桥接模式将继续关系转换为关联关系,从而降底了类与类之间的耦合,降底类的个数。
 
模式定义:
    将抽象部分与它的实现部分分离,使它们都可以独立地变化。即:不只改变你的实现,也改变你的抽象。
 

 
结合图2来理解模式的定义,“ 将抽象部分与它的实现部分分离 ”:即是将基础图形与颜色分离,基础图形是抽象部分,上色是实现部分。“ 使它们都可以独立地变化 ” :基础图形与颜色都有各自的父类,都可以自由扩展。
 
演示代码:    
定义图形的父类及子类,作为示例,只写了矩形和正方形的子类;而且我们把图形作为桥接模式中的抽象部分,担象部分的行为是以实现部分实现的,所以图形类都有颜色类(实现部分)的引用
/**
 * 图形父类
 * @author yuhq
 *
 */
public abstract class Shap {
 /**
  * 绘制图形
  * @param color 上色器
  */
 public abstract void doDraw(Color color);
}


/**
 * 矩形子类
 * @author yuhq
 *
 */
public class Rectangle extends Shap{
 public void doDraw(Color color) {
  String cr = color.doColor();
  System.out.println("正在绘制"+cr+"颜色的矩形");
 }
}


/**
 * 正方形
 * @author yuhq
 *
 */
public class Square {
 public void doDraw(Color color) {
  String cr = color.doColor();
  System.out.println("正在绘制"+cr+"颜色的正方式形");
 }
}
/**
 * 颜色父类
 * @author yuhq
 *
 */
public abstract class Color {
 public abstract String doColor();
}




/**
 * 红色子类
 * @author yuhq
 *
 */
public class Red extends Color{
 public String doColor() {
  return "红色";
 }
}



/**
 * 绿色子类
 * @author yuhq
 *
 */
public class Green {
 public String doColor() {
  return "绿色";
 }
}
 
//这里的Main方法即是图3中的Client,通过该Client可以绘制各种带颜色的图形

public class DrawMain {
 public static void main(String[] args) {
  //绘制红色矩形
  Shap rectangle = new Rectangle();
  Color red = new Red();
  rectangle.doDraw(red);
 
  //绘制绿色色矩形
  Color green = new Red();
  rectangle.doDraw(green);
 
 }
}
 
输出结果: 
 
 
深入思考:
    桥接模式的关键是如何将变化的维度分离出来,并确定谁是抽象部分,谁是实现部分。
    上述绘图的例子较为简单,而且基础图形和颜色谁是抽象部分,谁是实现部分区别不大,再举一个贴近我们生活的例子:设计一个新的接口友好的电视遥控器程序,让所有遥控器斟于相同的抽象,而对此抽象又做出许多不同的实现--每部不同型号的电视都有自己的遥控器实现。
    分析:你不会第一次就做对遥控器的用户界面,事实上,我们希望随着可用性数据收集得越来越丰富的同时,持续改良遥控器。困难之处在于:遥控器(不断改良 )会改变,而电视机也会改变。你已经将用户界面抽象出来,所以可以根据不同电视机改变它的实现。事情还不只这样,随着时间 的增长,用户会对此界面提出一些想法,你还必须应对他们的反馈来改变抽象。
    先看一种简单直接的设计,如下图:
 
设计遥控器的抽象类,不同的型号的电视有不同的实现。这种设计简单粗爆,完全没有考虑到未来的变化:遥控器需要不断改良,为不同用户设计不同的遥控器。所以这里会发生变化的有两个维度:遥控器、不同电视对遥控器的实现。

现在有了两个层次结构,一个是遥控器,一个是平台特定的电视机实现,有了桥接的存在,可以独立的改变这两个层次。
 
桥接的优点:
    1、将实现予以解耦,让它和界面之再永久绑定。
    2、抽象和实现可以独立扩展,不会影响到对方。
    3、对于“具体的抽象”所做的改变,不会影响到客户。
桥接的用途和缺点:
    1、适合使用在需要跨越多个平台的图形和窗口系统上。
    2、当需要用不同的方式改变接口和实现时,你会发现桥接模式很好用。
    3、桥接模式的缺点是增加了复杂度。 

 
 

桥接模式(Bridge Pattern)的应用一 

 
 
 

猜你喜欢

转载自hqfish.iteye.com/blog/2183701