18.企业应用架构模式 --- 基本模式

1.入口
	入口是一个封装外部系统或资源访问的对象。
	当访问这种外部资源的时候,通常需要获得他们的api。但是这些api可能具有天然的复杂性,因为他们必须考虑到资源自身的特性。任何人要理解一个资源就必须通晓其api,
  无论是针对关系数据库jdbc还是sql,还是针对xml的w3c和jdom,皆是如此。这不仅使得软件可读写差,也使得软件的修改变得很困难,例如将来在某个时刻把关系数据库中的
  一些数据转移到xml消息中就会很棘手。
  	解决这类问题的途径很简单。将所有特定的api的代码封装到一个类中,这个类的接口看起来像一个常规对象。其他对象通过这个入口来访问资源,入口类将简单的方法调用
  转变成相应的特定api。	
  	
  	1.运行机制
  		事实上这是一个十分简单的 包装器模式。封装外部资源,创建一个简单的api,并用入口将对该api的调用转移到外部资源上。
  		入口的重要用途之一是它可以作为使用服务桩的一个极佳位置。你可以经常修正入口的设计,以使它更容易使用服务桩模式。一个使用得当的服务桩可以使得系统更易于
  	  测试,因而降低了编程的难度。
  	  	应尽可能保持入口简单。入口的基本功能包括适配外部服务和提供一个设计服务桩的良好位置。入口应在完成这些功能的前提下最小化,任何更复杂的逻辑应该放在入口的
  	  客户中。
  	  	一般而言,使用代码自动生成器来创建入口是不错的主意。通过定义外部资源结构,就可以生成一个对它进行封装的入口类。你可以使用关系元数据来创建一个关系表的
  	  包装器类,或者使用一个xml模式或dtd来生成一个xml文档的入口代码。
  	  	有时候需要用多个对象来构造入口,常见的形式是使用2个对象:一个后端合一个前端。后端封装对外部资源操作的代码,但并不简化其api。前端将外部资源的复杂api转化
  	  成应用程序可用的,更为简单的操作。如果封装外部服务并将之适配成你需要的形式相当复杂,这种方法就很有用,因为每个类处理一部分职责。

  	2.使用时机
  		如果必须通过一个复杂的接口与可能位于系统之外的事务交互,你应该考虑入口模式。使用入口将复杂性封装起来,而不要让复杂性蔓延到整个系统中。使用入口几乎没有
  	  什么弊端,同时又可以使系统中入口类之外的代码可读写显著提高。
  	  	通过为服务桩部署提高一个清晰的位置,入口模式使系统更易于测试。即使外部系统的接口易于使用,入口仍然是使用服务桩的首选点。
  	  	入口一个显而易见的优点是使你用一种资源来替换另一种资源变得更为容易。对资源的任何变化都只需要修改入口类即可---变化不会传播到系统中的其余部分。入口是一个简单
  	  高效的变更保护形式。
  	  	如果你有数个子系统,将它们解耦的另一种选择是映射器。但是,映射器比入口更复杂,因此,使用入口来完成大部分外部资源的访问。
  	  	1.外部模式对比较复杂的api进行简化,其通常由服务的作者提供,而且是通用的。入口则是客户方为了其特定应用而编写的。此外,一个外观通常暗示一个与原始接口不同的
  	    接口,但是入口中可以只是简单的照搬被包装的接口,这种入口用于将来替换资源或测试目的。
  	    2.适配器模式修改某一已经实现的接口,使其与另一个你使用到的接口相匹配。入口模式中通常没有一个已存在的接口,虽然你可能会使用一个适配器来将实现映射到一个入口类的
  	    接口上。此时适配器是入口类实现的一部分。
  	    3.调停者模式通常用来将多个对象解耦,使它们无需互相引用,而只要与调停者发生关联。入口模式中通常只涉及两个对象,而且被包装的资源并不知道入口的存在。

2.映射器
	在两个独立的对象之间建立通信的对象。
	有时你会需要在两个子系统之间建立通信,但这2个子系统又必须互相隔离。这种情况发生的原因可能是你无法修改这2个已有的子系统,或者是你可以但不愿意在两个子系统之间建立
  依赖关系,甚至不愿意在它们与另一个独立部件之间建立依赖关系。

  	1.运行机制
  		映射器是子系统之间的绝缘层,控制着这些子系统之间的通信细节,但其存在并不为任何一个子系统所感知。
  		映射器通常需要在层与层之间进行数据交互。这种数据交互一旦被激活,工作方式就是显而易见的。映射器的难点在于如何激活,因为你无法再被映射子系统中的任何一方直接
  	  调用它。有时可以使用一个第三方的子系统来完成映射并调用映射器。另一个可选的方案是让映射器成为某个子系统的观察者。通过监视子系统发生的事件,映射器就可以调用了。
  	  	映射器的工作方式取决于它所映射的层的类型。我们最常见的映射器是数据映射器。

  	2.使用时机
  		从本质上说,映射器的作用是将系统的不同部分解耦。当你想做到这一点的时候,可以在映射器或入口之间做选择。入口无论是在代码编写还是后期使用都比映射器简单的多。
  	  所以,只有当你需要确保没有任何一方子系统依赖于子系统之间的交互时,才应使用映射器。只有在一种情况下,即子系统之间的交互很复杂,且这交互多少独立于两个子系统
  	  的主要目标时,这点才重要。在企业级应用中,我们通常会发现映射器用于与数据库的交互,即数据映射器。

3.层超类型
	某一类型充当一层中所有类型的超类型。
	以下这种情况并非罕见:某一层中所有的对象都具有某些方法,但你并不希望这些方法在系统内被多次复制而产生冗余代码。此时你可以将这些行为移到一个通用的层超类型中。

	1.运行机制
		这一模式中,存在一个层中所有对象的超类,共有的接口都被重构到这一超类中。如果你在一层中有多个对象,则可以有多个层超类型。

	2.使用时机  	
		当软件某一层中所有对象有公共特性时就可以使用层超类型。  

4.分离接口
	在一个包中定义接口,而在另外一个与这个包分离的包中实现接口。
	当开发系统时,你可以通过减少系统部件之间的耦合程度来改进设计质量。减少耦合的一个较好方法是将类分组,然后组织成包,并限制包间的依赖关系。这样你就可以对包间调用
  加入某些规则,这些规则用来确定一个包中的类是否能调用另一个包中的类。
  	但是,你可能需要调用某些与包之间一般性依赖关系有冲突的方法。在这种情况下,可以使用分离接口模式:在一个包中定义接口,但在另一个包中实现接口。此时,与接口有依赖
  关系的客户完全无法感知到实现的存在。分离接口为入口提供了一个良好的插入点。

  	1.运行机制
  		该模式的使用很简单,核心在于利用以下事实:实现类对接口存在依赖关系,反之却不然。这就意味着你可以将接口和实现放在不同的包中,实现包到接口存在依赖关系。其他的
  	  包只依赖于接口包而与实现包没有依赖关系。
  	  	当然,如果接口脱离了实现,软件就无法工作了。这可以通过在编译时使用另一个独立的包来将接口与实现链接起来,也可以在软件配置的时候使用插件模式。
  	  	分离接口的难点之一在于如何实例化其实现。这通常需要与实现类有关的信息。通常使用的方法是是用欧冠一个独立的工厂对象,而且对工厂而言有一个分离的接口,你同样需要
  	  将工厂的接口与其实现绑定。插件是解决这一绑定的好方法,它不仅可以使消除依赖关系,而且可以推迟到配置时再决定哪一个实现类。如果你不想使用插件,一个简单的办法是让
  	  另一个包在应用程序启动的时候实例化实现类,这个包与接口机器实现皆有关联。对于任何一个使用分离接口的对象,它们尽可以在启动时实例化自身,也可以实例化工厂包。

  	2.使用时机
  		当你需要打破系统两个部分之间的依赖关系时,可以使用接口分离。以下为一些例子:
  		1.你为通常的情况编写了一些抽象代码,并把这些代码放到一个框架包中,框架包需要调用一些特定的应用代码。
  		2.一层中的某些代码需要调用另外一个层的代码,但调用者又不应知道被调用者的存在,例如,领域层代码调用数据映射器就是这种情况。
  		3.你需要调用另一开发小组的函数,但是又不想与他们所提供的api产生依赖关系

  		对于应用程序的开发者来说,建议只有当你希望打破依赖关系,或者同一接口有多个独立的实现才使用一个分离接口。如果你把接口和实现放在一起,再在将来某一时刻将它们
  	  分开也不过是一个简单的软件重构,完全可以将它推迟到你必须如此时再实施。

5.注册表
	一个众所周知的对象,其他对象可以通过该对象找到公共的对象和服务。
	当你希望定位某一对象时,通常会从另一个与其有关的对象入手,通过关联来查找目标对象。注册表实际上是一个全局对象。

	1.运行机制
		与其他对象一样,你必须从接口以及实现两个方面来考虑注册表的设计。与许多对象一样,二者是完全不同的。
		首先应该考虑的是接口。对注册表而言,倾向于在接口中使用静态方法。类的静态方法在应用程序中任何地方都很容易找到。而且,可以将所需的逻辑封装在静态方法中,包括对其他
	  方法的委托,可以是静态的,也可以是实例。但是,方法的静态性并不意味着你的数据也必须保存在静态域中。事实上,除了保存常数以外,几乎不会使用任何静态域。
	  	在决定以何种方式保存数据之前,你应该先考虑数据的作用域。注册表中的数据可以根据不同的执行上下文而改变。一些数据的作用域贯穿整个进程;一些只是对线程而言是全局的;
	  一些对某次会话是全局的。不同作用域要求不同的实现,但他们的接口是一致的。应用程序员并不需要知道调用某个静态方法后返回的进程作用域还是线程作用域的数据。你可以对不同的
	  作用域有不同的注册表,但也可以只有一个注册表,这个注册表在不同的作用域有不同的方法。

	2.使用时机
		尽管包含了对方法的封装,注册表从本质上而言仍是一个全局数据,因此用起来并不是那么容易。
		有许多可取代注册表的方法。一种途径是通过参数形式来传递经常需要用到的数据。另外一种方法是为在对象创建时把指向公共数据的引用传递给它。

6.值对象
	一个如货币或日期范围这样的小而简单的对象,判等时并不根据标识id。
	在由多种类型对象组成的对象系统中,区分引用对象和值对象是有用的。二者之中值对象通常规模小一些;它类似于许多非纯粹面向对象持续设计语言中的原始类型。

	1.运行机制
		通常来说,我们倾向于认为值对象是小对象,如货币对象或日期对象;而引用对象是大对象,如订单或顾客。
		引用对象和值对象的关键区别在于它们判别两个对象是否相等的方法。引用对象的判等是基于标识---可能是程序设计系统的内部标识,如面向对象的程序设计语言内建的标识,或者是
	  某种类型的id号,如关系数据库中的主键。而值对象的判等则是根据内部的属性值。例如,如果两个日期对象的日,月,年值均相等,则这个2个对象相等。
	  	在对这2种对象进行处理时其区别就表露无遗。值对象较少而且易于创建,因此它们作为参数传递时通常是传值而不是传引用。你不会真正去关心系统中有多少个值为2001年3月18日的
	  对象。你也不会关心两个对象引用是否实际上指向同一个物理对象,或者它们是否拥有不同的但值相等的拷贝。
	  	值对象不应该作为完整记录而持久化,应该把它作为嵌入值或序列化lob。值对象较少,因此嵌入值往往是最佳选择,因为它允许sql查询使用值对象中的数据。

	2.使用时机
		当某事物的判等不是基于其标识时,你就可以将其作为值对象处理。对于任何小且易于创建的对象也可以考虑使用值对象。

7.货币
	表示一个货币值。

8.特殊情况
	针对特殊情况提供特殊行为的子类。
	空值对于面向对象的程序来说难以处理,因为它会破坏多态性。通常可以在一个给定类型的引用变量之上自由调用诸如foo之类的方法,而不用担心该引用所指向的是否为给定类型还是它的一个
  子类。对于强类型语言来说,你甚至可以让编译器来检查这一调用是否正确。但是,由于一个引用变量可能为空,因此你可能会因为调用控制对象的方法而产生运行时错误,这会引发一个异常并
  显示出错时的堆栈跟踪列表。
  	如果一个变量的值可能为空,就必须记得在使用它之前进行空值测试,这样才能确保及时其值为空也可以正常运行。通常,正确的事在许多上下文中是相同的,因此你在程序中许多地方都书写
  相似的判空代码 --- 这会造成大量的冗余代码。

  1.运行机制
  	基本思想是创建一个处理特殊情况的子类。例如,你有一个顾客对象而且你想避免空值检查,你可以创建一个'空顾客'对象。在特殊情况子类中重载所有的顾客类方法,提供一些无害的行为。
  然后,只要你有一个空值,你就使用一个空顾客对象来替代它。

  2.使用时机
  	当你在系统中有多处地方需要在对某一特定类的实例进行条件检测的时候,然后做相似的动作,或者在空值检测后做相同的动作,你就可以应用特殊情况模式。	

9.插件
	在配置时而非编译时连接类。
	当应用程序代码需要在多个环境中运行,且每个环境下对特定行为需要不同实现时,通常会使用分离接口模式。大多数开发人员通过编写一个工厂方法来在不同环境下生成相应的实现。假定
  通过分离接口来定义你的主键生成器,以便你可以使用一个简单的内存计数器来进行软件的单元测试,而在真实产品中使用由数据库管理的序列。你的工厂方法很可能包含一个条件判断语句,这
  一语句检查一个局部环境变量以确定系统是否处于测试模式,并返回正确的主键生成器。当你有数个工厂以后,你的手头就会变得一团糟。建立一个新的部署配置,需要在多个工厂中修改条件语句,
  然后重新编译和部署。配置工作不应该如此分散在整个应用程序中,也不应该需要重新的编译和部署。插件模式通过提供集中化的,运行时配置的方法来解决这些问题。

  1.运行机制
  	首先要做的是通过分离接口定义所有那些在不同运行环境下有不同实现的行为。除此之外,我们还使用基本的工厂模式,只对它增加了若干特殊的要求。插件工厂要求指明某一环境下,接口
  与哪一个实现连接的指令在一个单独的,代码之外的地方进行声明,以便配置具有可管理性。此外,与实现的连接必须是在运行时动态进行的,而不是在编译时进行的,这样才能在重配置后无需
  重新编译。
  	文本文件可以很好的描述连接规则。插件工厂只不过简单的读取文本文件,查找指定当前环境下所需接口对应哪个实现的项,然后返回相应的实现。
  	插件模式在具有反射机制的程序语言中可以充分发挥其优势,因为工厂可以动态构造实现对象,而无需在编译时就与实现类存在依赖关系。当使用反射机制时,配置文件必须包含从接口名到
  实现类名的映射。工厂可以独立置于框架包中,而且当在配置中增加新的实现类时无需改变工厂。
  	即使没有使用支持反射机制的程序语言,插件仍然有其存在的价值,它创建了一个中心配置点。仍然可以用一个文本文件来设定连接规则,唯一的区别在于你的工厂将使用一个条件逻辑判断来
  来将接口映射到实现。每一个实现类型在工厂中都要考虑到 --- 实际中的实现类型的数量不会太多。一旦你在代码中增加了一个新的实现类,你所需要做的只是在工厂的方法中增加一个新的选项。
  为了执行层间和包间依赖关系的编译检查,你可以将工厂放到一个独立的包中以避免破坏编译过程。

  2.使用时机	
  	只要有行为在不同运行环境下要求不同的实现时,就应该使用插件模式。

10.服务桩
	在测试时移除对有问题服务的依赖。
	企业级系统通常需要依赖于第三方服务(例如信用服务,税率查询和价格引擎)的访问,有这类系统开发经验的人都知道:如果依赖于完全不受自己控制的外部资源,通常会使得软件项目受挫。
  第三方服务的特性是不可预知的,而且这些服务通常是远程的,因而软件性能和可靠性也会受到损害。
  	这一问题最起码减缓了开发进程。开发人员要么坐在计算机面前无所事事的等待服务结果通过线路返回,要么对代码进行大量的删改以使其兼容已发布的接口。更糟糕而又极可能发生的情况是,
  这种依赖关系可能会导致测试无法进行,从而使得开发周期成倍增长。当测试无法进行时,开发进程就无法向前推进。

  	1.运行机制
  		首先使用入口来定义一个服务的访问点。入口不应该只是一个类,而应该是一个分离接口。这样就可以有一个调用时机服务的实现和至少一个服务桩的实现。所需的入口实现应该以插件
  	  的方式载入。编写服务桩的关键在于使之尽可能的简单---复杂性只会令你无法实现你的目的。

  	2.使用时机
  		当你发现对某一特定服务的依赖妨碍你的开发和测试时,就应该使用服务桩。
  		许多极限编程的实践者会使用术语'模拟对象'来代替服务桩。

11.记录集
	表格数据在内存中的表现方式。
	过去20年中,在数据库中表示数据的主流方式是关系表格形式。记录集模式的思想是通过一个在内存中的数据结构来提供解决这一问题的完整方案,该结构看起来与sql查询的结果即为相似,
  但是它可以由系统中其他部件来生成和操作。

  	1.运行机制
  		记录集通常无需你亲自创建,而是由所用的软件平台的销售商提供的。
  		记录集最根本的一点在于它看起来很像数据库查询的结果。这意味着你可以使用传统的两层结构,即发布一个查询并把数据直接传递给数据相关的用户界面,从而使得你可以充分利用
  	  所有的快速开发用户界面的工具的便利性。其次,可以很容易自己创建一个或者从数据库查询中得到一个记录集,而且可以很容易利用领域逻辑代码操作它。

  	2.使用方法
  		当你有一个环节依赖于记录集结构并将之作为操作数据的通用方法时,记录集就有了其存在的价值。

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
企业应用架构模式.pdf》是一本关于企业应用架构模式的书籍。企业应用架构模式是指在设计和开发企业级应用程序时所采用的一种模式化的方法。这本书介绍了一些常见的企业应用架构模式,并提供了详细的实例和解释。 企业应用架构模式对于企业级应用程序的设计和开发非常重要。通过采用适当的架构模式,可以帮助开发者更好地管理和组织复杂的系统,提高系统的可维护性和可扩展性。通过了解这些模式,开发者可以更好地理解系统的整体结构和组成部分之间的关系。 这本书中介绍的企业应用架构模式包括层次结构、服务导向架构、事件驱动架构等。这些模式在实际的企业应用程序中被广泛应用。例如,层次结构模式将应用程序划分为不同的层次,每个层次都有不同的责任和功能,这有助于更好地组织代码和提高系统的可维护性。服务导向架构则强调将应用程序划分为一系列的服务,通过服务之间的通信来实现系统的功能。事件驱动架构则基于事件的触发和响应来实现系统的逻辑。 这本书的内容不仅限于理论知识的介绍,还提供了大量的实例和案例分析。通过这些案例,读者可以深入了解各种架构模式的实际应用和实施过程。同时,书中也提供了一些建议和最佳实践,帮助读者在实际开发中更好地应用这些架构模式。 总结来说,《企业应用架构模式.pdf》是一本介绍企业级应用程序架构模式的书籍。通过学习这本书,读者可以了解不同的架构模式,并应用于实际的企业级应用程序开发中。这对于提高系统的可维护性和可扩展性非常有帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值