桥接模式

一、概述

一般问题:一个类需要在两个以上维度扩展,采用继承方式会导致子类数量过多

核心方案:将抽象部分与实现部分分离,使其都可以独立变化

设计意图:桥接模式不是将两个不相干的类链接,而是将一个需要多维度变化的类拆分成抽象部分和实现部分,并且在抽象层对两者做组合关联,是用组合的方式来解决继承的问题。举个例子,如果一个类在两个维度分别有m和n种变化,采用继承的方式就需要扩展出m*n个子类,且一个维度每增加一种变化就多出另一个维度变化总数的子类;如果将两个维度拆分再组合,加起来也只有m+n个子类,且每个维度独立扩展,一个维度增加一种变化只需要增加1个子类。

如上图,Abstraction就是桥接模式中的“桥”,它含有一个实现部分实例,且提供动态设置具体实现类地方法,这样抽象部分和实现部分的子类可以随意组合。

下面举一个简单的例子:夏天都喜欢吃烧烤,就以烧烤为例,我们从两个维度分析:从食材上有鸡翅、鸡腿等;从风味上有微辣、特辣等。

我们把食材做为抽象部分,把风味作为实现部分:

 

先看实现部分变化:

风味类Spicy

 public interface Spicy{
       String taste();
 }

微辣SlightSpicy

public class SlightSpicy implements Spicy{
     public String taste(){
          return "微辣";
     }
}

特辣ExtraSpicy

public class ExtraSpicy implements Spicy{
     public String taste(){
          return "特辣";
     }
}

再看抽象部分变化:

烧烤类Barbecue

public abstract class Barbecue{
     protected Spicy mSpicy;    //实现部分实例
     public Barbecue(Spicy spicy){    桥接模式的关键,组合实现和抽象
          this.mSpicy= spicy;
     }
     public abstract void eat();
}

鸡翅类ChickenWing

public class ChickenWing extends Barbecue{
    public ChickenWing (Spicy spicy){
         super(spicy);
    }
     public void eat(){
           System.out.println( "鸡翅:"+super.mSpicy.taste());
     }
}

测试:

public class Test{
     public static void main(String[] args){
         Barbecue barbecue = new ChickenWing(new SlightSpicy());
         barbecue .eat();
         Barbecue barbecue2 = new ChickenWing(new ExtraSpicy());
         barbecue2 .eat();
     }
}

输出:

鸡翅:微辣
鸡翅:特辣

二、实战应用

 我们知道Android中ListView的Adapter的设计用到了适配器模式,实际上Adapter本身还包含在一个桥接模式之中!

上图是整个AdapterView类图,对比桥接模式的UML图,不难看出整体上它是个大的桥接模式,我们抽取其中的AbsListView这个小的桥接模式来分析:

AbsListView表示集合视图,其有两个维度变化:

  1. 显示形式变化,如列表形式ListView或网格形式GridView;
  2. 数据类型变化,如字符串数组SimpleAdapter或数据库游标CursorAdapter

Android将显示形式作为抽象部分,数据类型作为实现部分,两个部分各自独立变化。

抽象部分和实现部分在AbsListView抽象层做了组合关联,体现代码如下:

public abstract class AbsListView extends AdapterView<ListAdapter>{
  ListAdapter mAdapter;    
  @Override
    public void setAdapter(ListAdapter adapter) {
        if (adapter != null) {
            mAdapterHasStableIds = mAdapter.hasStableIds();
            if (mChoiceMode != CHOICE_MODE_NONE && mAdapterHasStableIds &&
                    mCheckedIdStates == null) {
                mCheckedIdStates = new LongSparseArray<Integer>();
            }
        }
        clearChoices();
    }
}

三、总结

总结:桥接模式是一种结构型设计模式,根据最小继承原则,将各个变化部分分离,从而实现独立变化互不干涉,但又在更高的抽象层实现组合以保证各子类能动态结合。

用一句话来概括桥接模式:

“打断骨头还连着筋”

优点:

  • 抽象和实现分离
  • 易于扩展

缺点:桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。

 

posted @ 2019-06-13 16:07  西贝雪  阅读(2753)  评论(0编辑  收藏  举报