结构型模式中的适配器模式、外观模式、装饰模式、代理模式都属于包装模式,都是对另外的类或对象的包装,仅仅是各自的意图不同。

适配器模式通过对另外的类或对象的包装,将其接口转换为用户期望的接口,达到接口适配的目的。

外观模式是对包装的一组类或对象提供一个高层接口,意图是简化接口,使系统更加easy使用。

装饰模式的意图是在不改变包装对象接口的情况下为其添加另外的功能或职责。

代理模式的意图是通过对包装对象的包装以便控制对包装对象的訪问。

适配器模式、外观模式对客户提供的接口与其包装类的接口有所不同,也就是这两种模式对客户来说改变了包装类的訪问接口。而装饰模式、代理模式对外不改变所包装类的接口,对客户提供的接口与包装类的接口同样。

1、适配器模式

适配器模式包含两种:类适配器模式和对象适配器模式,一种使用了继承方式,一种使用了对象组合方式,相关的UML类图例如以下:

Android系统中适配器模式大量採用,因为ANDROID採用的是JAVA语言,而JAVA语言不支持多继承,因此在系统中採用的适配器模式主要是另外一种,用来把包装对象的接口转换为须要的接口。

在Android系统中最经常使用的採用适配器模式的类为继承于BaseAdapter的类,如ArrayAdapter、CursorAdapter等,用来在底层数据和AdapterView视图之间提供适配,把对底层数据的读取接口转换为视图须要的接口。类图例如以下:

继承于AdapterView的视图(Client)通过Adapter(Target)的接口函数获得视图须要的数据,如Adapter接口函数getItem(int
position)从底层数据集获得位置position的数据项,getCount()函数获得数据集中的数据项的个数。

Adapter的详细类完毕与不同底层数据类型读取接口的适配,如CursorAdapter类通过Cursor对象读取底层数据库中的数据,ArrayAdapter用来读取随意类型列表数组中的数据,HistoryAdapter用来读取类型为HistoryEntry的向量中的数据。

其他採用适配器模式的还有显示服务中DisplayAdapter类以及打印服务中的PrintDocumentAdapter类。DisplayAdapter用来适配不同类型的显示设备,用来侦測和发现系统连接的不同类型的设备。PrintDocumentAdapter用来适配不同的打印输出目标设备,如打印机或者文件,用来在这些设备输出打印内容。

2 、外观模式

外观模式的类图例如以下:

在Android 系统中使用的外观模式的地方比較多,能够说每一个系统服务都对客户提供了一个訪问该系统服务的管理门户类,用来方便訪问相应的系统服务,如窗体管理服务相应的WindowManager,输入管理服务相应的InputManager,活动管理服务相应的ActivityManager等等。

另外ContentResolver、Log、Context、ServiceManager也能够看作门户模式的採用。

ContentResolver用来为应用提供訪问数据模式的公共接口,Log为应用提供使用log输出系统的公共接口,Context为应用提供訪问整个系统的接口。ServiceManager提供訪问其他系统服务的入口。

3 、装饰模式

装饰模式的类图例如以下:

在Android系统中也有不少使用装饰模式的样例。如ContextThemeWrapper类及其派生类Activity和Service。UML类图例如以下:

ContextWrapper是对ContextImpl类的包装,Service类和Activity类都是ContextWrapper的派生类,Service类直接派生自ContextWrapper,Activity间接派生自ContextWrapper的子类ContextThemeWrapper,Service类和Activity类分别在ContextWrapper和ContextThemeWrapper类的接口基础上加入和实现了各自的生命周期回调接口(钩子),Activity类还提供了与其相关的窗体和视图显示相关的功能。ContextThemeWrappe的功能是在ContextWrapper基础上加入了对主题(Theme)的支持及在通过getSystemService接口返回服务管理对象时对于LAYOUT_INFLATER_SERVICE服务做了特殊处理,採用原形模式返回一个LayoutInflater对象的克隆对象。

4 、代理模式

      代理模式的类图例如以下:

在Android系统中代理模式也是普遍採用,每个系统服务和本地服务都相应一个远端代理类,用来实现跨进程的訪问系统服务或本地服务。每个系统服务为一个Stub对象,而client通过一个Proxy对象訪问相应的Stub对象。如管理管理服务相应的类图例如以下:

WindowManagerGlobal作为客户通过继承于接口IWindowManager的一个代理对象IWindowManager.Stub.Proxy跨进程訪问系统服务WindowManagerService。

5  、桥接模式

桥接模式的意图为:将抽象部分与它的实现部分分离,使它们都能够独立地变化。这里的抽象和实现指的不是类的抽象和实现,而能够理解为功能抽象(或界面)和功能实现。不论什么具有实现关系的两个独立演化派生的类之间都能够构成桥接模式,桥接模式主要用在须要跨越多个平台的图形和窗体系统上。如全部介绍桥接模式的书中差点儿都是以不同特性的窗体与窗体功能的实现,不同的视图(或图形)与视图(或图形)的绘制作为採用桥接模式的样例。例如以下为桥接模式的类图结构:

相同在ANDROID系统中不同的视图构成的视图树与完毕视图的绘制功能的类之间,以及窗体类与窗体的功能实现类之间也能够觉得採用的是桥接模式。相关类图例如以下:

图中不同的视图如Button、ImageView、TextView构成了一个抽象派生层次视图树,在视图树中View是全部视图的根视图,View的绘制通过三个不同的能独立演化的类来实现:Canvas(提供绘制表面)、HardwareLayer(提供输出显示层)、DisplayList(代表一个绘制操作)。

例如以下为ANDROID系统中窗体与窗体实现类之间的类图。Window、PhoneWindow构成窗体的抽象部分,Window是抽象部分的抽象接口,Window眼下仅仅提供了一个详细类PhoneWindow,Window的实现部分相关的类也构成了一个派生类图,WindowManager为窗体实现部分的基类,WindowManagerImpl为WindowManager的详细类,WindowManagerImpl通过WindowManagerGlobal并通过IWindowManager接口与窗体管理服务WindowManagerService交互,由窗体管理服务完毕实际的窗体管理功能。

桥接与适配器两个模式很类似,仅仅是使用场合和观察角度不同。

在GOF所著的设计模式经典著作中对桥接模式与适配器模式的差别描写叙述为:B r i d g e模式的结构与对象适配器类似,两个模式的不同之处主要在于它们各自的用途和出发点:B r
i d g e目的是将接口部分和实现部分分离和桥接,从而对它们可以较为easy也相对独立的加以改变和演化,B r i d g e模式可以为用户提供一个稳定的抽象和事实上现接口。而A d a p t e r模式通过改变一个已有对象的接口,用来解决两个已有接口之间的不匹配,帮助实现不兼容的类之间协同工作,A
d a p t e r模式不考虑这些接口是如何实现的,也不正确其又一次设计,也不考虑它们各自可能会如何演化。因此A d a p t e r通常在系统设计完毕后使用,而B r i d g e模式必须事先知道一个抽象将有多个实现部分,因此在系统開始时就被使用。

因此从上面的描写叙述能够看出:对一个採用桥接或适配器模式的已经完毕的代码,从不同的观察角度能够看作桥接模式,也能够看作适配器模式。

6 、组合模式

组合模式的意图为:将对象组合成树形结构以表示“部分-总体”的层次结构。C o m p o s i t e使得用户对单个对象和组合对象的使用具有一致性。例如以下为类图结构:

採用组合模式的标准样例为图形、视图、菜单和窗体等,集合类(如数组)、文件文件夹也能够看作採用了组合模式。例如以下为ANDROID系统中採用组合模式的组合视图类图:

7 、享元模式

享元模式的意图为运用共享技术有效地支持大量细粒度的对象,类图结构例如以下:

享元模式也是普遍採用的模式。

在ANDROID系统中,每一个应用组件都能够使用系统提供的众多服务管理对象,如WallpaperManager、AccessibilityManager、CaptioningManager、AccountManager等等。因此为了在一个组件内共享这些对象,在应用组件的Context的实现ContextImpl中,在ContextImpl类第一次载入引用时为每一个管理对象都创建了一个ServiceFetcher对象(採用静态代码块),并依据服务名字把新创建的ServiceFetcher对象放到MAP集合中,每一个ServiceFetcher对象在登记到MAP集合中时都分配了一个索引。

应用组件在调用Context.getSystemService来获得系统服务管理对象时,首先依据服务名字从MAP集合中获得相应的ServiceFetcher对象,然后调用ServiceFetcher对象的getService函数获得ServiceFetcher对象创建的服务管理对象。

在ServiceFetcher对象的getService函数中首先从Context维护的Cache数组列表中依据ServiceFetcher对象的索引查找是否已经包括有ServiceFetcher对象创建的服务管理对象,假设在Cache中存在服务管理对象,则直接返回Cache中保存的服务管理对象,否则调用ServiceFetcher的createService函数创建一个服务管理对象,并依据其索引放置到Cache中,以便下次使用。

版权全部,请转载时清楚注明出处和链接,谢谢!




ANDROID 中设计模式的採用--结构型模式的更多相关文章

  1. OOAD-设计模式(四)结构型模式之适配器、装饰器、代理模式

    前言 前面我们学习了创建型设计模式,其中有5中,个人感觉比较重要的是工厂方法模式.单例模式.原型模式.接下来我将分享的是结构型模式! 一.适配器模式 1.1.适配器模式概述 适配器模式(Adapter ...

  2. 组合模式(Composite Pattern) ------------结构型模式

    组合模式使用面向对象的思想来实现树形结构的处理和构件,描述了如何将容器对象和叶子对象进行递归组合,实现简单,灵活性好. 组合模式(Composite Pattern):组合多个对象形成树形结构以表示具 ...

  3. 桥接模式(bridge pattern)-------结构型模式

    桥接模式是一种对象结构型模式,其将抽象部分和它的实现部分分离,使它们都可以独立的变化,又称为柄体(Handle and Body)模式或接口(Interface)模式. 优点: 1.分离抽象接口及其实 ...

  4. 设计模式学习之桥接模式(Bridge,结构型模式)(15)

    参考地址:http://terrylee.cnblogs.com/archive/2006/02/24/336652.html 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化, ...

  5. 设计模式学习之组合模式(Composite,结构型模式)(10)

    转载地址:http://www.cnblogs.com/zhili/p/CompositePattern.html 一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系 ...

  6. 设计模式学习之装饰者模式(Decorator,结构型模式)(16)

    参考地址:http://www.cnblogs.com/zhili/p/DecoratorPattern.html 一.定义:装饰者模式以对客户透明的方式动态地给一个对象附加上更多的责任,装饰者模式相 ...

  7. 设计模式学习之代理模式(Proxy,结构型模式)(11)

    参考地址:http://www.cnblogs.com/zhili/p/ProxyPattern.html 一.引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访 ...

  8. 设计模式学习之享元模式(Flyweight,结构型模式)(20)

    转:http://terrylee.cnblogs.com/archive/2006/03/29/361767.html 摘要:面向对象的思想很好地解决了抽象性的问题,一般也不会出现性能上的问题.但是 ...

  9. 外观模式(Facade)---结构型模式

    1 基础知识 定义:提供了一个统一的接口(外观类),用来访问子系统中的一群接口.特征:定义了一个高层接口让子系统更容易使用,减少了外部与子系统内多个模块的耦合. 本质:封装交互,简化调用. 优点:简化 ...

随机推荐

  1. 结合Wireshark捕获分组深入理解TCP/IP协议之以太网帧

    摘要:     本文摘抄并整理了以太网相关理论知识,包括CSMA/CD协议机制及工作.LAN互连,详细分析了Ethernet II帧格式,最后给出Ethernet II帧实例. 一.以太网[1] 1. ...

  2. 21、根据(应用程序)虚拟驱动vivi的使用过程彻底分析摄像头驱动(有ioctrl分析)

    videobuf2-core.h中的vb2_buffer,记录了v4l2_buffer ,驱动可以对vb2_buffer的v4l2_buffer进行操控, vb2_buffer是v4l2框架层的代码, ...

  3. C++项目參考解答:累加求圆周率

    [项目-累加求圆周率] 用例如以下公式求π的近似值(计算直到最后一项的绝对值小于10−5) π4=1−13+15−17+... [參考解答] #include <iostream> usi ...

  4. AngularJS之ng-options指令

    1.基本下拉效果(lable for value in array) 其中select标签中的ng-model属性必须有,其值为选中的对象或属性值. <div ng-controller=&qu ...

  5. ztree实现左边动态生成树,右边为具体信息功能

    页面原型图: 图片.png 功能需求:点击左边树上的子节点,像后台发送请求,将请求到的信息展示在右边的表单里面 前端代码实现: 引入css文档: <link rel="styleshe ...

  6. Bash Shell 的管道命令

    1.cut: 命令选取 cut -d'分隔字符' -f fields -d :后面接分隔字符.用-f一起使用 -f: 根据-d的分隔字符将一段信息分割成为数段 -c:以字符的单位取出固定字符区间 Eg ...

  7. 菜单之一:Menu基础内容 分类: H1_ANDROID 2013-11-03 00:23 906人阅读 评论(0) 收藏

    参考<疯狂android讲义>2.10节P168 1.重要接口 Android菜单相关的重要接口共有以下四个: 其中Menu为普通菜单,SubMenu包含子项,ContextMenu当长时 ...

  8. 创建ListView的基本步骤 分类: H1_ANDROID 2013-10-31 23:25 1276人阅读 评论(0) 收藏

    参考<疯狂android讲义>第2.5节P94 1.创建一个或者多个ListView <LinearLayout xmlns:android="http://schemas ...

  9. Android中的消息机制:Handler消息传递机制 分类: H1_ANDROID 2013-10-27 22:54 1755人阅读 评论(0) 收藏

    参考<疯狂android讲义>第2版3.5 P214 一.背景 出于性能优化考虑,Android的UI操作并不是线程安全的,这意味着如果有多个线程并发操作UI组件,可能导致线程安全问题.为 ...

  10. mysql分区功能(三个文件储存一张表)(分区作用)(分区方式)

    mysql分区功能(三个文件储存一张表)(分区作用)(分区方式) 一.总结 1.mysql数据表的存储方式(三个文件储存一张表): 一张表主要对应着三个文件,一个是frm存放表结构的,一个是myd存放 ...