你能解释一下Contextdevise模式吗?
我已经开始阅读关于Contextdevise模式 。 以下是我从文中理解的内容:
-
你有一个包含所有variables的地图
-
你把它传递给需要它的人,这样你就不必把所有的variables都作为方法参数发送出去
我“得到”了吗?
我想你明白了。
但是,我也认为这是一个更应该避免的反模式。 看看这里为什么。
也参见得墨忒耳法
我“得到”了吗?
对不起,说不完。
上下文对象的目标不是将大量的参数隐式地传递给方法,作为绕过强打字和封装的手段。 其目标是以范围广泛的pipe理方式存储范围内的数据,而不依赖于协议和表示技术。 存储在范围内的数据本质上是共享的,仍然可以是结构化的,并且本质上不同于传递给方法的一次性参数。
上下文对象模式是在Core J2EE Patterns 2nd Ed中首次引入的。 “上下文”部分是指对象在范围的上下文中保存数据的事实
(如application/session/request/conversation/flash
)。
它的目的是尽可能地从协议/表示技术特定的类(如HttpSession
和HttpRequest
)中分离应用程序数据和逻辑。
模式实施
在上下文对象下,用于应用程序/会话/请求/其他范围的数据不直接放入ServletContext
/ HttpSession
/ HttpRequest
/其他协议特定的类中。 相反,数据存储在POJO包装类中,然后位于ServletRequest
/ HttpSession
/ HttpRequest
/ other中。
上下文对象可以将数据存储在地图中,但不需要 – 它可以以与程序相关的任何结构/格式存储数据。
一个应用程序可以使用每个范围的一个Context对象类,或者有序地分割数据的几个类,避免过度的Class膨胀和促进关注的分离。
上下文对象由最前面的表示类(视图,前端控制器,分派器)使用。 这些表示客户端对象调用contextObject.get来检索存储的作用域数据,contextObject.put来存储作用域上下文数据。
它不被传入业务/集成逻辑。 它不被用作将大量parameter passing到业务对象的方式,绕过强大的input。 业务和集成层面由业务代表,应用服务和/或会话外观使用特定的强types参数。
模式的好处
- 可testing性:unit testing只需要模拟一个简单的POJO,而不是一个协议特定的复杂服务器类,比如
ServletContext
或者HttpRequest
- 灵活性和可重用性:应用程序的核心工作独立于瘦协议特定的“表示”类层。 这意味着应用程序可以更容易地更改或添加协议或表示技术(例如HTML / HTTP / Servlet和WAP / Servlet和XML / SOAP / HTTP / EJB和HTML / HTTP / JSF)。
注释
- 是一种历史模式
- 有人可能会争辩说,dependency injection框架,如CDI,Guice,Spring,Seam和其他人给范围存储已经以独立于协议的方式实现。 即所有的范围已经被实现为上下文对象,这意味着开发者不需要创build额外的上下文对象。 这并不否定这种模式 – 这意味着CDI框架已经支持这种模式。
- 如果实施不当,最终可能会出现“遍历应用程序中的多重上下文对象”反模式
引用KaptajnKold:我想你明白了。 但是,我也认为这是一个更应该避免的反模式。 看看这里为什么。
您的评论指的是上下文对象的错误实现版本。 上下文对象本身不是反模式。
上下文对象提供对共享数据和函数的访问。
它可以是一个优雅和灵活的替代品:
- 全局
- 单身
- 长参数列表
ACCU提供了更详细的描述。
如果您想要Java中的上下文模式的真实世界示例,请查看Google Android API 。
在使用上下文模式时,您需要注意您的依赖关系图 。 (这就是KaptajnKold把它称为反模式的原因。)
为了限制不必要的依赖性,可以为不同的目的使用不同的上下文 保持您的上下文尽可能简单,并在需要时使用组合或inheritance来增加复杂性。