• 设计模式(五)桥接模式


    1.定义

     将抽象部分与实现部分分离,使它们都可以独立的变化。

    2.介绍

       举个生活中的例子,一条数据线,一头USB接口的可以连接电脑、充电宝等等,另一头可以连接不同品牌的手机,通过这条数据线,两头不同的东西就可以连接起来,这就是桥接模式。

    3.UML类图

    角色说明:

    • Abstraction(抽象化角色):一般是抽象类,定义该角色的行为,同时保存一个对实现化角色的引用。
    • Implementor(实现化角色):接口或者抽象类,定义角色必需的行为和属性。
    • ConcreteImplementorA、ConcreteImplementorB(具体实现化角色):实现角色的具体行为。

    4.实现

    这里以穿衣服为例,不同职业的人可能要穿的衣服不一样。

    4.1 创建实现化角色

    定义一个衣服接口:

    interface Clothes {
            String getName();
    }

    4.2 创建具体实现化角色

    创建两种衣服类:校服和衬衫。

     1 public class Uniform implements Clothes {
     2 
     3      @Override
     4      public String getName() {
     5           return "校服";
     6      }
     7 }
     8 
     9 public class Shirt implements Clothes {
    10 
    11      @Override
    12      public String getName() {
    13           return "衬衫";
    14      }
    15 }

    4.3 创建抽象化角色

    定义一个人物类,有一个穿衣服的方法,并且持有衣服类的引用。即抽象化角色持有实现化角色的引用,可以调用实现化角色的方法,达到桥接的作用。

    1 public abstract class Person {
    2      Clothes mClothes;//持有衣服类的引用
    3 
    4      public void setClothes(Clothes clothes) {
    5          mClothes = clothes;
    6      }
    7 
    8      protected abstract void dress();//穿衣服
    9 }

    4.4 创建具体抽象化角色

    这里有两种角色穿衣服:学生和程序员。

     1 public class Student extends Person {
     2 
     3     @Override
     4     protected void dress() {
     5         System.out.println("学生穿上" + mClothes.getName());
     6     }
     7 }
     8 
     9 public class Coder extends Person {
    10 
    11     @Override
    12     protected void dress() {
    13         System.out.println("程序员穿上" + mClothes.getName());
    14     }
    15 }

    4.5 客户端测试:

     1 public void test() {
     2         //创建各种衣服对象
     3         Clothes uniform = new Uniform();
     4         Clothes shirt = new Shirt();
     5         
     6         //不同职业的人穿衣服
     7         Person coder = new Coder();
     8         coder.setClothes(shirt);
     9         coder.dress();
    10 
    11         System.out.println("--------------------------------------");
    12         Person student = new Student();
    13         student.setClothes(uniform);
    14         student.dress();
    15 
    16         System.out.println("--------------------------------------");
    17         student.setClothes(shirt);
    18         student.dress();
    19 }
    20 
    21 输出结果:
    22 
    23 程序员穿上衬衫
    24 --------------------------------------
    25 学生穿上校服
    26 --------------------------------------
    27 学生穿上衬衫

    4.6 其他说明:

    通过上面的例子可以看到,我们分离了两端的变化。新增衣服和新增职业都变的非常简单。假如我们再增一个维度的变化,例如加个年龄来区分怎么办?这时我们就可以把Person类作为实现化角色,把不同年龄段作为抽象化角色,代码就不写了,有兴趣可以去实现一下。

    5. 应用场景

    • 一个类存在两个或以上的独立维度的变化,且这些维度都需要进行拓展。
    • 不希望使用继承或因为多层次继承导致类的个数急剧增加时。
    • 如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承关系,可以通过桥接模式使他们在抽象层建立一个关联关系。

    6. 优点

    • 分离了抽象与实现。让抽象部分和实现部分独立开来,分别定义接口,这有助于对系统进行分层,从而产生更好的结构化的系统。
    • 良好的扩展性。抽象部分和实现部分都可以分别独立扩展,不会相互影响。

    7. 缺点

    • 增加了系统的复杂性。
    • 不容易设计,抽象与实现的分离要设计得好比较有难度。

    8. Android中的源码分析

    桥接模式在Android中的源码应用还是非常广泛的。比如AbsListViewListAdapter之间就是一个桥接模式。

    8.1 AbsListView 与 ListAdapter 之间的桥接模式

    相关代码就不贴了,看下它们的UML类图就明白了。

    这里AbsListView是抽象化角色,ListAdapter则是实现化角色。

    8.2 其他

    另外,Window 与 WindowManager 之间也是桥接模式。有兴趣的可以去看下源码体会体会。

  • 相关阅读:
    qt鼠标事件总结(坐标,跟踪,点击判断)
    从零开始学C++之RTTI、dynamic_cast、typeid、类与类之间的关系uml
    前端篇: 前端演进史
    找一款防文件或文件夹误删除,移动,修改的软件
    yyyy
    盘点我用过的那些网盘(那些年,我们一起玩的网盘)
    Win8/8.1/10获得完整管理员权限的方法
    [置顶] IT老男人读《因为痛,所以叫青春》
    dddd
    用JUNCTION映射文件夹内容 解决多系统跑同一个虚拟机而共享文件夹路径不同的问题
  • 原文地址:https://www.cnblogs.com/ganchuanpu/p/7011712.html
Copyright © 2020-2023  润新知