架构设计.doc_第1页
架构设计.doc_第2页
架构设计.doc_第3页
架构设计.doc_第4页
架构设计.doc_第5页
已阅读5页,还剩46页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

UML培训总结 2010-12-14 来源:网络这两天参加了公司组织的UML培训,培训者是火龙果软件公司的老师。通过两天课程的学习,对UML的使用有了更系统,深刻的认识。之前对UML的使用,仅限于画图,写文档,而且很多时候都是代码完成了再反向工程得到类图,根据类图画出顺序图,最后把UseCase补上,就完工了。和标准的使用顺序刚好相反,呵呵。1.业务建模在系统UseCase图之前,应该有业务UseCase图,主要是对业务需求的描述,它的Actor称为Business Actor(业务Actor),Business Actor可能最终并不是我们系统中的使用者,但是,从用户的角度,从提出业务需求者的角度,Business Actor是最直接能想到的,也是最重要的。例如,保险公司理赔系统中,Business Actor就是投保人,而实际上投保人并不会操作我们的管理系统,理赔专员,审核员,复核员等才是是系统Actor,但是在与业内人士确定需求时,肯定是以投保人为中心,投保人投保时需要提供什么信息,理赔时需要提供什么信息等。有了业务UseCase图,就可以开始画活动图,也成泳道图,要尽可能详细,全面的描述客户的需求,此时并不用考虑哪些部分是系统实现的部分,关键在于能够把业务逻辑完整的表述出来。就是什么人(Actor),做了什么事(业务事件),产生了什么结果(业务实体,单据等)。注意,跨泳道的交互必须要有业务实体,即交互的数据。2.需求建模对活动图进行分析,得到系统UseCase图。就是要确定活动图中哪些业务事件是我们系统需要实现的,哪些部分是用户自己去做的。把系统需要做的业务事件归纳合并整理,得到UseCase,并对UseCase进行归纳整理。主要有三种归纳方法:include,extend和泛化。include是把重复的提出来;extend是备选流,对主业务流的补充,例如超市管理系统中,收银员收银这个UseCase,扫描仪无法扫描条形码,收银员手工输入就是备选流,查询不到商品信息的处理也是备选流;泛化是对过程类似的UseCase进行提炼,例如武松打虎,李逵杀虎,孙悟空打老虎三个UseCase,可以归纳出一个即打虎,只是行为人,实用工具,结果,方式不一样而已。3.领域分析从UseCase和活动图中找出类,主要有UI类,控制类,实体类,边界类(outerface),画顺序图。顺序图是对象之间的交互,对象一定要包含实体类,与实体类的连线以后就是该实体的方法了,注意尽量把对实体中数据的操作作为该实体的方法。顺序图完成后,就从中抽象,提炼出类。并不是我之前的操作过程,先设计类,再画顺序图,对于简单的业务逻辑,是可以这么做的,一旦业务逻辑过于繁琐,之前也没有接触过,也不理解时,就可见从顺序图提炼类图是多么的关键了。因为顺序图是从活动图来的,活动图直接对应的就是业务需求。提炼类是注意分配职责给类,而不仅仅是数据,把职责和数据绑定到一起。GRASP职责分配模式:信息专家模式,创建者模式,高内聚模式,低耦合模式,控制器(协调者)模式,中介者。类之间的关系有4种:依赖关系,关联关系,继承关系和实现接口。依赖关系用虚线箭头表示,是方法级别的,类A在某个方法中使用了自定义类B,那么A依赖B;继承关系是实现和三角形表示,实现接口用虚线和三角形表示,都是类级别的;关联关系是属性级别的,类A的某个属性是自定义类B,那么类A和B就是关联关系,分为组合和聚合两种,如果B的实例必须在A中创建,不能单独存在,随着A的消亡和消亡,那么就是聚合关系,用实心菱形和实线箭头表示,如人和眼睛,就是这种关系。另一种,B的实例也可以独立存在,和A只是一种组合,生命周期没有必然的联系,是组合关系,用空心菱形和实线箭头表示,例如电脑和鼠标。如果行为逻辑比较复杂,设计多次循环,多方协调,事件驱动,用流程图可能不好描述,或者业务规则比较负责包含多个维度,就需要使用状态图。状态图有三种:基本,复合,并发。如果某个类的多个属性都含有状态,即有多个维度的状态,就需要用到复合或者并发了。原则:把复杂问题简单化,简单的业务逻辑,很容易理解的,完全可以不画,但是对于负责的逻辑,尤其是涉及到算法的业务,必须要画出,只用分析设计,画图了,才能理清业务规则和关系,再进行提炼,合并和重构,就能化繁为简,也能方便日后的维护。4.面向对象设计先划分子系统,因为需要从用户的角度建立功能划分,再设计层,每个子系统可能有自己的层次结构,最后设计类和包。组件图,部署图就在这一步完成。面向对象的设计原则类设计原则 2009-06-11 来源:网络在面向对象设计中,如何通过很小的设计改变就可以应对设计需求的变化,这是令设计者极为关注的问题。为此不少OO先驱提出了很多有关面向对象的设计原则用于指导OO的设计和开发。下面是几条与类设计相关的设计原则。 1. 开闭原则(the Open Closed Principle OCP) 一个模块在扩展性方面应该是开放的而在更改性方面应该是封闭的。因此在进行面向对象设计时要尽量考虑接口封装机制、抽象机制和多态技术。该原则同样适合于非面向对象设计的方法,是软件工程 设计方法的重要原则之一。我们以收音机的例子为例,讲述面向对象的开闭原则。我们收听节目时需要打开收音机电源,对准电台频率和进行音量调节。但是对于不同的收音机,实现这三个步骤的细节往往有所不同。比如自动收缩电台的收音机和按钮式收缩在操作细节上并不相同。因此,我们不太可能针对每种不同类型的收音机通过一个收音机类来实现(通过重载)这些不同的操作方式。但是我们可以定义一个收音机接口,提供开机、关机、增加频率、降低频率、增加音量、降低音量六个抽象方法。不同的收音机继承并实现这六个抽象方法。这样新增收音机类型不会影响其它原有的收音机类型,收音机类型扩展极为方便。此外,已存在的收音机类型在修改其操作方法时也不会影响到其它类型的收音机。 图1是一个应用OCP生成的收音机类图的例子:图1 OCP应用(收音机)2. 替换原则 (the Liskov Substitution Principle LSP)子类应当可以替换父类并出现在父类能够出现的任何地方。这个原则是Liskov于1987年提出的设计原则。它同样可以从Bertrand Meyer 的DBC (Design by Contract) 的概念推出。我们以学生为例,夜校生为学生的子类,因此在任何学生可以出现的地方,夜校生均可出现。这个例子有些牵强,一个能够反映这个原则的例子时圆和椭圆,圆是椭圆的一个特殊子类。因此任何出现椭圆的地方,圆均可以出现。但反过来就可能行不通。 Liskov的相关图示见图2:图2 Liskov 原则运用替换原则时,我们尽量把类B设计为抽象类或者接口,让C类继承类B(接口B)并实现操作A和操作B,运行时,类C实例替换B,这样我们即可进行新类的扩展(继承类B或接口B),同时无须对类A进行修改。 3. 依赖原则 (the Dependency Inversion Principle DIP) 在进行业务设计时,与特定业务有关的依赖关系应该尽量依赖接口和抽象类,而不是依赖于具体类。具体类只负责相关业务的实现,修改具体类不影响与特定业务有关的依赖关系。在结构化设计中,我们可以看到底层的模块是对高层抽象模块的实现(高层抽象模块通过调用底层模块),这说明,抽象的模块要依赖具体实现相关的模块,底层模块的具体实现发生变动时将会严重影响高层抽象的模块,显然这是结构化方法的一个硬伤。面向对象方法的依赖关系刚好相反,具体实现类依赖于抽象类和接口(见图-3)。为此,我们在进行业务设计时,应尽量在接口或抽象类中定义业务方法的原型,并通过具体的实现类(子类)来实现该业务方法,业务方法内容的修改将不会影响到运行时业务方法的调用。 图3依赖原则图示4. 接口分离原则(the Interface Segregation Principle ISP)采用多个与特定客户类有关的接口比采用一个通用的涵盖多个业务方法的接口要好。ISP原则是另外一个支持诸如COM等组件化的使能技术。缺少ISP,组件、类的可用性和移植性将大打折扣。这个原则的本质相当简单。如果你拥有一个针对多个客户的类,为每一个客户创建特定业务接口,然后使该客户类继承多个特定业务接口将比直接加载客户所需所有方法有效。图4展示了一个拥有多个客户的类。它通过一个巨大的接口来服务所有的客户。只要针对客户A的方法发生改变,客户B和客户C就会受到影响。因此可能需要进行重新编译和发布。这是一种不幸的做法。图4 带有集成接口的服务类我们再看图-5中所展示的技术。每个特定客户所需的方法被置于特定的接口中,这些接口被Service类所继承并实现。 图5 使用接口分离的服务类设计如果针对客户A的方法发生改变,客户B和客户C并不会受到任何影响,也不需要进行再次编译和重新发布。 以上四个原则是面向对象中常常用到的原则。此外,除上述四原则外,还有一些常用的经验诸如类结构层次以三到四层为宜、类的职责明确化(一个类对应一个具体职责)等可供我们在进行面向对象设计参考。但就上面的几个原则看来,我们看到这些类在几何分布上呈现树型拓扑的关系,这是一种良好、开放式的线性关系、具有较低的设计复杂度。一般说来,在软件设计中我们应当尽量避免出现带有闭包、循环的设计关系,它们反映的是较大的耦合度和设计复杂化。UML 状态图2010-12-23 作者:佚名 来源:网络 状态和状态机 状态、状态表示法及状态机 状态是指在对象生命周期中满足某些条件、执行某些活动或等待某些事件的一个条件和状况 一个状态通常包括名称、进入/退出活动、内部转换、子状态和延迟事件等五个部分组成 状态机是计算机科学理论的一部分,但UML中的状态机模型主要是基于David Harel所做的扩展,是用来展示状态与状态之间转换的图 如何阅读状态机图 阅读最简单的状态? 最为核心的元素无外乎是两个:一个是用圆角矩形表示的状态(初态和终态例外);另一个则是在状态之间的、包含一些文字描述的有向箭头线,这些箭头线称为转换转换的五要素 源状态:即受转换影响的状态 目标状态:当转换完成后对象的状态 触发事件:用来为转换定义一个事件,包括调用、改变、信号、时间四类事件 监护条件:布尔表达式,决定是否激活转换、 动作:转换激活时的操作 读图小结 与状态off相关的转换有两个,其触发事件都是turnOn,只不过其监护条件不同。如果对象收到事件turnOn,那么将判断壶中是否有水;如果没水,则仍然处于off状态;如果有水则转为on状态,并执行“烧水”动作。 而与状态on相关的转换也有两个,如果“水开了”就执行turnOff,关掉开关;如果烧坏了,就进入了终态了 转换类型 描述 语法 外部转换 对事件做出响应,引起状态变化或自身转换,同时引发一个特定动作,如果离开或进入状态将引发进入转换、离开转换 事件(参数)监护条件/动作 内部转换 对事件做出响应,并执行一个特定的活动,但并不引起状态变化或进入转换、离开转换 事件(参数)监护条件/动作 进入转换 当进入某一状态时,执行相应活动 entry/活动 退出转换 当离开某一状态时,执行相应活动 exit/活动 只有动作描述,进入和退出和操作方法写在了里面 各种转换的区别 进入和退出转换:当进入一个状态时,执行某个动作;或当退出某个状态时,执行什么动作。这时就可以使用进入和退出转换来表示 内部转换:用来处理一些不离开该状态的事件活动与延迟事件 活动:当对象处于一个状态时,它一般是空闲的,在等待一个事件的发生。但是某些时间,你可能希望描述个正在进行的活动。在处于一个状态的同时,对象做着某些工作,并一直继续到被某个事件中断 延迟事件:延迟事件是一种特殊的事件,它是指该事件不会触发状态的转换,当对象处于该状态时事件不会丢失,但会被延迟执行。例如,当E-mail程序中正在发送第一封邮件时,用户下达发送第二封邮件执令就会被延迟,但第一封邮件发送完成后,这封邮件就会被发送。这种事件就属于延迟事件复合状态表示法顺序复合状态图监护条件为“应答音”,代表已连接。并发复合状态图三种评测方式历史 “一个圆圈中加上字母H”,是用来表示历史状态的。 它的含义是:当从状态“结账”和“显示购物车”返回子状态“显示索引信息”时,将进入的是离开时的历史状态。也就是说,转到购物车或结账区之后,再回到“浏览目录”的页面时,其中的内容是不变的,仍然保留原来的信息。 子状态机将子状态机单独定义,并对其进行命名(通常以大写字母开头),然后在需要使用的地方来引用它 引用C状态机如何绘制状态机图绘制状态机图绘制状态机图的理想步骤是:寻找主要的状态,确定状态之间的转换,细化状态内的活动与转换,用复合状态来展开细节寻找主要状态:对于航班机票预订系统而言,显然包括的状态主要有 - 在刚确定飞机计划时,显然是没有任何预订的,并且在有人预订机票之前都将处于这种“无预订”状态 - 对订座而言显然有“部分预订”和“预订完”两种状态 - 而当航班快要起飞时,显然要“预订关闭” 总结一下,主要有四种状态:无预订、部分预订、预订完以及预订关闭 确定状态间转换 部分预订 不直接转换 关闭()预订关闭表格横向是转出预订完关闭()预订完无转换表格纵向是转入预订关闭部分预订不直接转换无转换源目标无预订退订(),使预订人=0退订()无转换无预订预订()预订(),无空座关闭()细化状态内的活动与转换使用复合状态状态机图应用说明对对象生命周期建模:主要描述对象能够响应的事件、对这些事件的响以及过去对当前行为的影响 对反应型对象建模:这个对象可能处于的稳定状态、从一个状态到另一个状态之间的转换所需的触发事件,以及每个状态改变时发生的动作 状态机图既可以用来表示一个业务领域的知识,也可以用来描述设计阶段对象的状态变迁本章小结 首先介绍了“状态”的概念和UML表示法,然后引入了状态机的概念 通过三个例子逐一说明简单状态机图、包含复杂转换的状态机图以及包含复合状态的状态机图的阅读方法 紧接着通过一个航班机票预订系统来阐述了状态图的绘制过程:确定状态,分析状态间的转换,细化活动与内部转化,通过复合状态来组织 简明地点出状态图的两大功能:对对象的生命周期建模以及对反应型对象的行为建模UML建模之时序图(Sequence Diagram) 2010-09-08 作者:灵动生活 来源:灵动生活的Blogs一、时序图简介(Brief introduction)时序图(Sequence Diagram)是显示对象之间交互的图,这些对象是按时间顺序排列的。顺序图中显示的是参与交互的对象及其对象之间消息交互的顺序。时序图中包括的建模元素主要有:对象(Actor)、生命线(Lifeline)、控制焦点(Focus of control)、消息(Message)等等。二、时序图元素(Sequence Diagram Elements)角色(Actor)系统角色,可以是人、及其甚至其他的系统或者子系统。对象(Object)对象包括三种命名方式:第一种方式包括对象名和类名;第二中方式只显示类名不显示对象名,即表示他是一个匿名对象;第三种方式只显示对象名不显示类明。生命线(Lifeline)生命线在顺序图中表示为从对象图标向下延伸的一条虚线,表示对象存在的时间,如下图控制焦点(Focus of Control)控制焦点是顺序图中表示时间段的符号,在这个时间段内对象将执行相应的操作。用小矩形表示,如下图。消息(Message)消息一般分为同步消息(Synchronous Message),异步消息(Asynchronous Message)和返回消息(Return Message).如下图所示:同步消息=调用消息(Synchronous Message)消息的发送者把控制传递给消息的接收者,然后停止活动,等待消息的接收者放弃或者返回控制。用来表示同步的意义。异步消息(Asynchronous Message)消息发送者通过消息把信号传递给消息的接收者,然后继续自己的活动,不等待接受者返回消息或者控制。异步消息的接收者和发送者是并发工作的。返回消息(Return Message)返回消息表示从过程调用返回自关联消息(Self-Message)表示方法的自身调用以及一个对象内的一个方法调用另外一个方法。Combined Fragments Alternative fragment(denoted “alt”) 与 ifthenelse对应 Option fragment (denoted “opt”) 与 Switch对应 Parallel fragment (denoted “par”) 表示同时发生 Loop fragment(denoted “loop”) 与 for 或者 Foreach对应 三、时序图实例分析(Sequece Diagram Example Analysis)时序图场景完成课程创建功能,主要流程有:1、请求添加课程页面,填写课程表单,点击【create】按钮2、添加课程信息到数据库3、向课程对象追加主题信息4、为课程指派教师5、完成课程创建功能时序图实例时序图实例分析1、序号1.0-1.3 完成页面的初始化2、序号1.4-1.5 课程管理员填充课程表单3、序号1.6-1.7 课程管理员点击【Create】按钮,并响应点击事件4、序号1.8 Service层创建课程5、序号1.9-1.10 添加课程到数据库,并返回课程编号CourseId6、序号1.11-1.12 添加课程主题到数据库,并返回主题编号topicId7、序号1.13 给课程指派教师8、序号1.14 向界面抛创建课程成功与否的消息四、总结(Summary)时序图(Sequence Diagram)是显示对象之间交互的图,这些对象是按时间顺序排列的。顺序图中显示的是参与交互的对象及其对象之间消息交互的顺序。时序图中包括的建模元素主要有:对象(Actor)、生命线(Lifeline)、控制焦点(Focus of control)、消息(Message)等等。最后,以课程创建功能演示一时序图实例。设计模式系列-桥接模式 2011-1-18 来源:网络一、我们讲述了比较常用的适配器模式,并且分析了适配器的一般使用场景: 1、我们在使用第三方的类库,或者说第三方的API的时候,我们通过适配器转换来满足现有系统的使用需求。 2、我们的旧系统与新系统进行集成的时候,我们发现旧系统的数据无法满足新系统的需求,那么这个时候,我们可能需要适配器,完成调用需求。 3、我们在使用不同数据库之间进行数据同步。(我这里只是分析的是通过程序来说实现的时候的情况。还有其他的很多种方式数据库同步)。 并且讲述了对象适配器和类适配器的区别: 对象适配器:不是通过继承的方式,而是通过对象组合的方式来进行处理的,我们只要学过OO的设计原则的都知道,组合相比继承是推荐的方式。 类适配器:通过继承的方式来实现,将旧系统的方法进行封装。对象适配器在进行适配器之间的转换过程中,无疑类适配器也能完成,但是依赖性会加大,并且随着适配要 求的灵活性,可能通过继承膨胀的难以控制。并且由于C#中不支持多继承,以至于限制我们的继承的策略。而对象组合的方式则不会有太多的限制。 我们在上篇中还讲述了适配器之间的转配,但是没有给出一个示例代码: 我们这里给出适配器之间相互转换的情况,有的时候,我们发现2个适配器之间也需要进行相应的转配,例如我们上面的数据库和XML文件的查询接口,例如有的时候,我需要把XML文件的数据转换到数据库中,或者把数据库中的数据保存成XML形式,这个时候,我们就需要定义一个对象,来完成相应的适配器之间的适配。 针对上面的说明,我们这里给出代码的核心部分: 旧系统的查询服务 public interface IQuery object Query(); public class DbQuery : IQuery public object Query() throw new NotImplementedException(); public class XMLQuery : IQuery public object Query() throw new NotImplementedException(); 旧系统的持久化服务: public interface ISave bool Save(object obj); public class XMLSave : ISave public bool Save(object obj) throw new NotImplementedException(); public class DbSave : ISave public bool Save(object obj) throw new NotImplementedException(); 新系统适配器持久化接口 public interface IPersistence bool Persistence(object obj); public class XMLPersistenceAdapter : IPersistence XMLSave save = new XMLSave();public bool Persistence(object obj) return save.Save(obj); public class DbPersistenceAdapter : IPersistence DbSave save = new DbSave();public bool Persistence(object obj) return save.Save(obj); 新系统查询服务适配器: public interface ISelect object GetList(); public class XMLQueryAdapter : ISelect private XMLQuery query = new XMLQuery(); public object GetList() return query.Query(); public class DbQueryAdapter : ISelect private DbQuery query = new DbQuery(); public object GetList() return query.Query(); 适配器之间的转配器: public interface IAdapterToAdapter object GetData();bool SaveData(); 通用的转配器实现方案: public class ConvertAdapter : IAdapterToAdapter private Dictionary settings = new Dictionary(); public ConvertAdapter() /从配置文件中读取要转换的适配器节点指点的关系,并且配置要调用的方法 settings.Add(, new AdapterSetting(); public object GetData() return settings.AdapterName.Query(); public bool SaveData() return settings.ToAdapterName.Persistence(this.GetData(); 这样就可以完成基本的转配服务,当然我里面没有实现出完整代码,这里只是给出思路,如果您有好的想法或者建议,可以留言回复,谢谢! 二、摘要 本文将会讲述结构性模式中的另外一个重要的模式-桥接模式,这个模式的主要特点呢,就是解决一个对象的可能变化的因素的多个方向的依赖性。有的时候一个对象,引起这个对象发生变化的因素很多,这个时候我们就可以考虑,把依赖具体实现,提升为依赖抽象,来完成对和变化因素之间的低耦合,提高系统的可维护性和扩展性。而且客户可能不知道某个因素是否发生变化或者其他的可能情况。当然桥接模式也是结构性模式中一个比较难理解的模式,我们的项目中可能使用的相对来说少一些。不过当我们的一个复杂的对象,有多个因素引起这个对象的状态发生改变的时候,我们就可以考虑使用桥接模式,将这些因素进行抽象,让这个对象依赖于这些抽象的因素,而不是具体的因素,这样就能很好的适应变化。我们来看看一个可能的场景,我们现在有一个底层的ORM,我们现在只支持CUD的操作,不支持查询服务,这个时候我们为了新增查询服务,那么我们怎么做呢?按照传统的方式,我们可能是通过继承来实现。这个时候,可能我们会如下来做,目前我们已经为这个ORM提供了SQL与ORACLE数据库的支持。 查询服务和缓存服务的时候,我们就必须基于现有的持久化服务来通过继承来扩展,扩展出一个缓存的ORM,一个查询方案的ORM,当然如果我们发现我们还需要扩展现有的服务的时候,我们又需要通过继承来完成,这是多么恐怖的一件事情啊,这等于有一个引起变化的因素发生改变后,就需要扩展一下上级的所有类进行继承,这是个乘法运算,我想我不用多解释,大家也是知道的!,所以这时候桥模式的出现,很的解决这个问题了,我们来看看桥接模式的类图吧: 桥接模式的意图就是解决这样的场景,上面将变化的因素进行抽象,然后具体的对象通过组合或者属性注入的形式来引用变化的因素,而这个依赖关系只是依赖的是因素的 抽象,这个时候,不会因为我们改变具体因素的实现,而修改用户程序中的复杂对象。这样就满足了设计模式的要求:将抽象部分与实现部分分离,使它们都可以独立的变化。 三、本文大纲 a、上篇回顾。 b、摘要。 c、本文大纲。 d、桥接模式的特点及使用场景。 e、桥接模式的经典实现。 f、桥接模式的其他方案。 g、桥接模式使用总结。 h、系列进度。 i、下篇预告。 四、桥接模式的特点及使用场景 4.1、桥接模式的特点桥接模式的主要目的是将一个对象的变化因素抽象出来,不是通过类继承的方式来满足这个因素的变化,而是通过对象组合的方式来依赖因素的抽象,这样当依赖的因素的具体实现发生变化后,而我们的具体的引用却不用发生改变,因为我们的对象是依赖于抽象的,而不是具体的实现。而且,通过这样的依赖抽象,我们在多个对象共享这样的因素的时候,就成为可能,如果我们使用的是具体的因素的共享,当我们改变这个变化因素的时候,我们必须把使用这个因素的所有的对象,都进行相应的修改,而如果所有的引用这个变化因素的对象都依赖于抽象而不是具体的依赖呢?这也为我们的共享的提供了变化性。 4.2、桥接模式的使用场景 1、当一个对象有多个变化因素的时候,通过抽象这些变化因素,将依赖具体实现,修改为依赖抽象。 2、当某个变化因素在多个对象中共享时。我们可以抽象出这个变化因素,然后实现这些不同的变化因素。 3、当我们期望一个对象的多个变化因素可以动态的变化,而且不影响客户的程序的使用时。 如何在项目中应用桥接模式,的确是个很难把握的问题,因为具体的项目中可能我们也会遇到这样的,当一个对象,可能会有多个维度的因素,引起对象变化时,我们就可以考虑使用请桥接模式来完成设计实现。 五、桥接模式的经典实现 我们上面讲了那么多,我们还是给出桥接模式的经典实现方案吧。不然我们讲的那么多,大家可能对具体的代码的实现并不是很清楚,怎么样才能实现满足桥接模式的方案呢? 我们这里还是以上面讲述的ORM的扩展为例来说明这样的方案的可行性和优缺点。具体的代码如下: 1、我们先给出抽象的接口,我们给出ORM最终的ORM接口:public interface IORM ISave Save get; set; IDelete Delete get; set; ICreate Create get; set; ICache Cache get; set; IQuery Query get; set; void Test(); 具体对象的变化因素的抽象接口定义 public interface ICreate bool Create(object o); public interface ISave bool Save(object o); public interface IDelete int Delete(int ID); 具体的ORM类的实现方案: public class ORM : IORM public ISave Save get throw new NotImplementedException(); set throw new NotImplementedException(); public IDelete Delete get throw new NotImplementedException(); set throw new NotImplementedException(); public ICreate Create get throw new NotImplementedException(); set throw new NotImplementedException(); public ICache Cache get throw new NotImplementedException(); set throw new NotImplementedException(); public IQuery Query get throw new NotImplementedException(); set throw new NotImplementedException(); public void Test() /测试缓存对象! this.Cache.Cache(new object(); 具体的调用是通过接口来进行调用的,所以我们给出几个简单的变化因素的实现类。 public class Delete : IDelete public int Delete(int ID) return 0; public class Create : ICreate public bool Create(object o) return true; 我们来看看具体的调用代码: public class Factory public static T Create() where T:class,new() T target = new T();return target; class Program static void Main(string args) IORM orm = new ORM(); orm.Create = Factory.Create(); orm.Cache = Factory.Create(); orm.Test(); 对于上面的实现思路,可能大家还不太明白,那么我贴出来变化因素与具体的对象之间的关系吧。我们这里假设有这么多变化的因素会影响到抽象类内部的行为,我们通过抽象的形式来解耦抽象类和变化因素之间的关系,来达到双方都能独立的发生变化。 我们通过抽象每个变化因素,让抽象类依赖与接口,然后我们通过属性注入的方式,或者构造函数注入的方式来注入到实现这个抽象类的具体类的内部。来完成组合对象的初始化操作。 我们来看看最后的处理情况如下: 我们这里通过构造函数注入,或者属性注入的方式来把需要使用的具体的变化因素注入到我们具体实现类中,完成对象的所有功能。 六、桥接模式的其他方案上面给出了桥接模式的经典模式,那么我们是不是可以有改进的方案呢?我们是不是可以结合之前讲解的一些模式的经验来探讨一下呢?答案是可以的,我们可以采用配置文件的形式来把具体实现的内容动态的注入到桥接模式中,我们来看看图形话的描述吧,来说明我这里给出的实现思路。 这里具体的实现代码我本篇就不贴出来了,具体的实现代码下篇开篇的时候,给出,由于本篇篇幅有限,下篇将会展开讲述这块的内容,希望大家见谅。 七、桥接模式使用总结 通过上面的简单描述,我们知道了桥接模式主要是为了解决,一个对象的多个维度的变化因素的变化太快,难以控制的问题,我们通过将每个维度的变化因素进行抽象, 然后我们的对象只要依赖于抽象即可,具体的实现调用我们不关心,通过对象组合的方式,我们就能组合出我们想要的对象。无疑这是一种非常灵活的也是满足设计模式的原则的,抽象和实现分离,使他们各自发生变化都不受对方的影响。而且我们也讲述了,使用桥接模式的几个典型的场景,现在我们的实际项目中就有这样的问题,我也是在项目的使用过程中加深对桥接模式的理解的,桥接模式为系统在多个维度的变化的适应性方面提供了很好的参考,特别适合底层框架的开发过程中使用,可以适应不同变化因素的改变,当然每个人对模式的理解深度和方向不同,由于本人水平有限,如果有错误之处,还请大伙多多指点,如果有好的建议和意见,请留言,我会细细品位,谢谢大家支持! 八、系列进度创建型 1、系统架构技能之设计模式-单件模式 2、系统架构技能之设计模式-工厂模式 3、系统架构技能之设计模式-抽象工厂模式 4、系统架构技能之设计模式-创建者模式 5、系统架构技能之设计模式-原型模式 结构型 1、系统架构技能之设计模式-组合模式 2、系统架构技能之设计模式-外观模式 3、系统架构技能之设计模式-适配器模式 4、系统架构技能之设计模式-桥模式 5、系统架构技能之设计模式-装饰模式 6、系统架构技能之设计模式-享元模式 7、系统架构技能之设计模式-代理模式 行为型 1、系统架构技能之设计模式-命令模式 2、系统架构技能之设计模式-观察者模式 3、系统架构技能之设计模式-策略模式 4、系统架构技能之设计模式-职责模式 5、系统架构技能之设计模式-模板模式 6、系统架构技能之设计模式-中介者模式 7、系统架构技能之设计模式-解释器模式十结构型设计模式Proxy Pattern(代理模式) 2010-12-20 来源:网络定义为其他对象提供一个代理或地方以控制对这个对象的访问。当客户向proxy对象第一次提出请求时,proxy实例化真实的对象,并且将请求传给它,以后所有的客户请求都经由proxy传给封装了的真实对象。proxy模式分为4种,用得最多的是远程和虚拟代理模式:1. Virtual Proxy(虚拟代理):Proxy不会生成一个真实的耗费代理,直到非常必要时(首次有请求)。它用来存放花费大(实例需要很长时间)的真实对象。2. Remote Proxy(远程代理):本地的代理对象控制一个远程的对象。3. Protection Proxy(安全代理):代理检查调用真实对象所需要的权限。4. Smart Reference(聪明引用):当调用真实的对象时,代理处理另外一些事。(1). 计算真实对象的引用次数,在没有引用时自动释放。(2). 首次被引用时装载存留(保存在硬盘或内存、数据库等)的对象。(3). 在访问时检查真实对象是否锁定,确保没有其他对象会改变它。UML类图如下:其中的类和对象的关系为:1. Proxy(代理):维护一个引用使得代理可以访问实体,如果RealSubject和Subject的接口相同,Proxy会引用Subject;提供一个与Subject的接口相同的接口,使得代理可以用来代替实体。有点想Adapter模式;控制对实体的访问并且负责创建及删除它;其他功能取决于Proxy的类型。* 远程代理:负责对请求及其参数进行编码,向不同的地址空间中的实体发送已编码的请求。* 虚拟代理:可以缓存实体的其他信息,以便延迟对它的访问。* 保护代理:检查调用者的请求是不是有所必需的权限。2. Subject(抽象实体接口):为RealSubject实体及Proxy代理定义相同的接口,使得RealSubject在任何地方都可以使用Proxy来访问。3. RealSubject(实体):定义Proxy代理的实体。典型应用的顺序图如下:实例1数学代理下面的例子就是应用远程代理来访问另外一个应用程序域中的对象。UML类图如下:系统架构技能之设计模式-组合模式 2011-1-18 来源:网络一、我们上篇主要讲述了结构型模式中的外观模式,外观模式作为结构型模式中的一个简单又实用的模式,外观模式通过封装细节来提供大粒度的调用, 直接的好处就是,封装细节,提供了应用写程序的可维护性和易用性。外观模式一般应用在系统架构的服务层中,当我们是多个不同类型的客户端应用程序时,比如一个系统既可以在通过Web的形式访问,也可以通过客户端应用程序的形式时,可能通过外观模式来提供远程服务,让应用程序进行远程调用,这样通过外观形式提供服务,那么不管是什么样的客户端都访问一致的外观服务,那么以后就算是我们的应用服务发生变化,那么我们不需要修改没一个客户端应用的调用,只需要修改相应的外观应用即可。 我们主要是讲述了以下的几种情况,使用外观模式可能更适合: 1、我们在使用第三方类库或者API的时候,我们通过本地的API接口的封装,来完成对第三方API接口的粗粒度外观对象,通过这个外观对象可以很容易的完成服务的调用。 2、我们在架构设计的过程中,一次的功能访问可能需要同时的调用很多个对象,那么如果我们在服务调用的时候,能够在应用程序调用中一次就能完成所有要同时调用的对象那该多好啊,外观模式无疑是最好的原则,特别是在分布式应用中,通过远程调用服务,通过外观模式降低应用程序与服务的交互次数,同时可以降低应用程序的复杂性。 二、摘要 本文将会讲述结构性模式中的另外一个常用的模式-组合模式,我们平时在面向对象的设计中,我想有一个原则经常被提及就是,我们在设计的时候,对象组合类的继承,本篇将会将结合简单的实例来说明这方面的优势,并且完成对组合模式的主题思想的掌握。我们这样来简单的理解组合模式,组合模式就是把一些现有的对象或者元素,经过组合后组成新的对象,新的对象提供内部方法,可以让我们很方便的完成这些元素或者内部对象的访问和操作。我们也可以把组合对象理解成一个容器,容器提供各种访问其内部对象或者元素

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论