通过上篇的简单讲解我们知道了组合模式意图是通过整体与局部之间的关系通过树形结构的形式进行组织复杂对象屏蔽对象内部的细节对外展现统一的方式来操作对象是我们处理更复杂对象的一个手段和方式。本文以查询控件为例说明了查询控件内部的组成元素及如何操作内部的组成元素包括添加元素删除和处理相应事件的Handler当然组合模式的作用远比这些强大后面我们肯定会在一些实例代码中运用到组合模式的。组合模式如果在条件允许的情况下我们尽量使用组合模式来处理复杂对象远比通过继承出来的对象来的有效。组合模式-强调的是如何组织整体和局部之间的结构将整体和局部之间的关系通过树形这样的结构来组织这种对象组合的结构关系。组合模式的适用场景1、我们期望操作一个复杂对象和操作一个组成这个复杂对象内部的简单对象一样操作的时候我们可以考虑对象组合。2、当一个对象由多个简单对象组成并且它又可能是其他对象的一个组成部分这种情况下组合模式是比较好的选择。二、摘要本篇将会讲述结构型模式中的经典模式-适配器模式,也是项目中经常使用的模式之一我们现在开发一个系统的时候也许会遇到各式各样的要求我们要求和现有的系统进行集成或者是我们直接开发一个系统或者是我们修改已有的系统达到满足现有需求的要求。因此一般来说每种情况我们都有自己的应对方案。我们来看看项目中的几种可能情况​编辑通过上面的几种情况我们知道开发一个新系统吧成本和时间的投入较高如果说我们旧系统目前运行的非常稳定并且投入的成本非常高我们既想继续使用旧系统的功能又想满足新系统的需求这个时候我们怎么做呢可能比较好的方式就是把旧系统通过适配器来转换成新接口的调用形式完成适配服务。当然本文也是主要针对这个思路展开去讲述适配器模式的一些用法当然我这里可能讲解了适配器模式的一些普遍用法还有一些比较特殊的用法需要大家多多指出向大伙学习了。本文主要讲述下面的几个部分的内容1、适配器模式的使用场景。2、适配器模式的经典实现。3、多适配器的封装。4、其他情况的考虑。三、本文大纲a、上篇回顾。b、摘要。c、本文大纲。d、适配器模式的特点及使用场景。e、适配器模式的经典实现。f、适配器模式的其他方案。g、适配器模式使用总结。h、系列进度。i、下篇预告。四、适配器模式的特点及使用场景4.1、适配器模式的特点适配器模式主要解决的问题就是我们要调用的接口类型无法满足我们新系统的使用需求这时候我们需要将旧系统的接口通过适配器进行转配达到支持新接口调用的目的。对于这样的要求我们通过适配器就可以完成当然如果有多个接口需要转配那么我们就需要为每一个接口提供一个适配器去完成转换的工作。当然具体的调用过程我们可以进行相应的封装。达到比较通用的方式去调用适配器完成适配服务。我们来看看适配的过程。​编辑上图基本给出了适配器的基本转换的过程。4.2、适配器模式的场景我们根据上面的适配器的特点的介绍中我们来分析下适配器模式的几类比较适用的使用场景1、我们在使用第三方的类库或者说第三方的API的时候我们通过适配器转换来满足现有系统的使用需求。2、我们的旧系统与新系统进行集成的时候我们发现旧系统的数据无法满足新系统的需求那么这个时候我们可能需要适配器完成调用需求。3、我们在使用不同数据库之间进行数据同步。(我这里只是分析的是通过程序来说实现的时候的情况。还有其他的很多种方式[数据库同步])。五、适配器模式的经典实现我们本节给出适配器模式的经典实现代码我们这里结合项目中的查询服务来进行说明旧系统中提供一个查询服务方法Query();但是我新系统定义底层的数据访问服务层的时候却是使用的GetList()方法并且将之前的返回结果集合进行包装成泛型的形式来进行。我们这里给出相关的示例代码大家就能清楚这个使用过程了当然我们这里给出类适配器和对象适配器2种实现的方式通过不同的实现思路我们最后总结下这2种形式的优缺点1、类适配器针对上面描述的接口的转配过程我们给出示例代码旧系统的查询服务public class Query IQuery{public object Query(){return new object();}}新系统的查询服务接口public interface ISelect{object GetList();}通过类适配器完成转配操作public class QueryAdapter : Query, ISelect{public object GetList(){return base.Query();}}具体的调用测试代码如下class Program{static void Main(string[] args){ISelect adapter new QueryAdapter();object o adapter.GetList();System.Threading.Thread.Sleep(10000);}}2、对象适配器旧系统的查询服务public class Query IQuery{public object Query(){return new object();}}新系统的查询服务接口public interface ISelect{object GetList();}通过类适配器完成转配操作public class QueryAdapter : ISelect{private Query query new Query();public object GetList(){return query.Query();}}具体的调用测试代码如下class Program{static void Main(string[] args){ISelect adapter new QueryAdapter();object o adapter.GetList();System.Threading.Thread.Sleep(10000);}}上面我们就完成了经典的适配器模式的简单实现当然上面也没有考虑通用性等各方面的内容只是给出了一个大概的实现当然对于上面的适配器的创建过程我们可以通过前面讲述的创建型模式中的几个实现方案进行相应的改进。六、适配器模式的其他方案上面给出了适配器模式的经典实现参考其他篇讲述的方式我们给出适配器模式的其他演变方式6.1、批量适配器的封装我们在项目中可能需要对一批的旧系统的接口进行封装这个时候我们可以通过配置文件的方式配置适配器。例如我们上面的查询可能我现在对于XML文件的查询方法与数据库的查询方法2个旧的查询服务进行封装然后我在实际的项目中通过配置来选择我使用哪个查询方法完成查询服务通过传入参数或者是配置节信息来进行控制。我们来看看相关的示例代码旧系统定义的查询服务接口public interface IQuery{object Query();}XML查询和数据库方式的实现public class XMLQuery : IQuery{public object Query(){throw new NotImplementedException();}}public class DbQuery : IQuery{public object Query(){throw new NotImplementedException();}}新查询服务接口public interface ISelect{object GetList();}具体的适配器代码实现public class XMLAdapter : ISelect{private XMLQuery query new XMLQuery();public object GetList(){return query.Query();}}public class DbAdapter : ISelect{private DbQuery query new DbQuery();public object GetList(){return query.Query();}}工厂来负责创建旧系统接口的服务的对象。public class AdapterFactory{public static ISelect CreateAdapter(){return (ISelect)Activator.CreateInstance(Type.GetType());}}具体的调用测试代码class Program{static void Main(string[] args){ISelect select AdapterFactory.CreateAdapter();object o select.GetList();}}6.2、通用适配器旧系统定义的查询服务接口public interface IQuery{object Query();}XML查询和数据库方式的实现public class XMLQuery : IQuery{public object Query(){throw new NotImplementedException();}}public class DbQuery : IQuery{public object Query(){throw new NotImplementedException();}}工厂来负责创建旧系统接口的服务的对象。public class OldFactory{public static IQuery CreateQuery(){return (IQuery)Activator.CreateInstance(Type.GetType());}}新查询服务接口public interface ISelect{object GetList();}具体的通用适配器代码实现public class ComAdapter : ISelect{IQuery query OldFactory.CreateQuery();public object GetList(){return query.Query();}