zoukankan      html  css  js  c++  java
  • 桥接模式

    一、概述

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

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

    设计意图:桥接模式不是将两个不相干的类链接,而是将一个需要多维度变化的类拆分成抽象部分和实现部分,并且在抽象层对两者做组合关联,是用组合的方式来解决继承的问题。举个例子,如果一个类在两个维度分别有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();
        }
    }

    三、总结

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

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

    “打断骨头还连着筋”

    优点:

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

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

  • 相关阅读:
    jzoj 3176. 【GDOI2013模拟5】蜘蛛侠
    各种各样的根号算法 总结&刷题
    jzoj 3187. 【GDOI2013模拟8】的士
    jzoj 3188. 【GDOI2013模拟8】找数
    jzoj 4673. 【NOIP2016提高A组模拟7.20】LCS again
    jzoj 4672. 【NOIP2016提高A组模拟7.20】Graph Coloring
    markdown 模板2
    树莓派kali开启arp【arpspoof,urlsnarf】
    Java 图片处理——如何生成高清晰度而占有磁盘小的缩略图
    手把手教你生成二维码-google.zxing
  • 原文地址:https://www.cnblogs.com/not2/p/11017132.html
Copyright © 2011-2022 走看看