你能解释一下什么是上下文设计模式吗?

80

我已经开始阅读关于上下文设计模式的内容。以下是我从文本中理解到的:

  • 你有一个包含所有变量的映射表

  • 你将它传递给需要它的人,这样你就不必将所有变量作为方法参数发送

我理解得对吗?


4个回答

105

我理解了吗?

抱歉,还没有完全理解。

Context Object 的目标不是为了通过隐式传递许多参数来绕过强类型和封装,而是以一种通用但受控的方式存储作用域数据,独立于协议和表示技术。作用域内存储的数据本质上是共享的,仍然可以被结构化,与传递给方法的一次性参数有根本的区别。

Context Object 模式最初是在Core J2EE Patterns 2nd Ed中提出的。'Context' 部分指的是对象将数据保存在一个作用域的上下文中(例如,application/session/request/conversation/flash)。

其目的是尽可能解耦应用程序数据和逻辑与特定于协议/表示技术的类之间的关系,如 HttpSessionHttpRequest

模式实现

在使用 Context Object 时,用于应用程序/会话/请求/其他范围的数据不会直接放入 ServletContext/HttpSession/HttpRequest/其他特定于协议的类中。相反,数据存储在一个 POJO 包装类中,然后放在 ServletRequest/HttpSession/HttpRequest/其他上。

Context Object 可能会将数据存储在 Map 中,但不需要 - 它可以将数据存储在任何适合程序的结构/格式中。

一个应用可能会使用一个作用域对应一个 Context Object 类,或者使用几个类以有序的方式分割数据,避免过多的 Class 膨胀,促进关注点的分离。

Context Object被前端表示类(Views, Front Controllers, Dispatchers)使用。这些表示客户对象调用contextObject.get来检索存储的范围数据和contextObject.put来存储范围上下文数据。

它不会传递到业务/集成逻辑中。它不被用作通过强类型绕过将多个参数传递到业务对象的手段。业务和集成层由Business Delegates、Application Services和/或Session Facades作为前端,使用特定的强类型参数。

模式好处

  • 可测试性:单元测试只需要模拟一个简单的POJO,而不是一个协议特定的复杂服务器类,如ServletContext或HttpRequest
  • 灵活性和可重用性:应用程序的核心独立于协议特定的“表示”类层。这意味着应用程序可以更容易地更改或添加协议或表示技术(例如HTML / HTTP / Servlet和WAP / Servlet和XML / SOAP / HTTP / EJB和HTML / HTTP / JSF)。

评论

  • 是一种历史模式
  • 可以说,依赖注入框架(如CDI、Guice、Spring、Seam等)已经以协议无关的方式实现了范围存储。也就是说,所有范围已经作为Context Objects实现,这意味着开发人员不太需要创建其他的Context Objects。这并不是否定这种模式——它意味着CDI框架已经支持这种模式。
  • 如果实现不正确,可能会出现“在整个应用程序中传递巨大的上下文对象”反模式

引用KaptajnKold的话: 我认为你懂了。 但是,我也认为它更像是一个要避免的反模式。在这里看看为什么here.

您的评论是针对实现错误的上下文对象版本而言的。上下文对象本身并不是一种反模式。


3
这让我想起了Win 32 API,你需要为单个方法调用创建一个巨大的对象,并将其作为参数传递,我认为这是一种反模式。许多属性仅与该单个方法调用相关,例如窗口大小和位置。上下文对象的属性不应如此短暂,并且应在当前范围内具有相关性和通用性。某些属性如根/父窗口将是有效的上下文信息。希望这能帮助人们思考和评估他们是否误用了该模式。这当然不是一门精确的科学。 - AaronLS

28

上下文对象提供共享数据和函数的访问。

它可以是以下内容的优雅且灵活的替代品:

  • 全局变量
  • 单例模式
  • 长参数列表

ACCU提供了更详细的描述。

如果您想在Java中看到上下文模式的实际应用,请查看Google Android API's

在使用上下文模式时,需要注意您的依赖图。 (这就是KaptajnKold称其为反模式的原因。)

为了限制不必要的依赖关系,为不同的目的使用不同的上下文。尽可能使上下文保持简单,并在需要时使用组合或继承来添加复杂性。


什么样的依赖关系图会导致上下文对象成为反模式? - thegreatcoder

0
一个使用上下文进行初始化的类。考虑以下代码。
public class BuildTagHandler extends TagHandler {

      public BuildTagHandler(ServiceContext context) {  // constructor
            this.tagDAO = context.getTagDAO();
            this.buildDAO = context.getBuildDAO();
      }

您将使用上下文来构建您的类。在上下文文件中,您将不会有实现,而是有大量的DAO对象。

您可以将其解释为外观模式,或者一个涵盖所有条目的巨大接口。


-1

上下文是一种反模式,因为它被用作先验未知内容的容器。


1
请不要对这个答案进行-1操作。上下文对象是一种反模式。在这里,将上帝对象作为参数传递到各个地方,而不是通过单例获取,不能阻止它成为上帝对象。 - Archibald
3
这并不是百分之百的真实情况,你可以通过创建一个特定上下文类的子类来指定哪些数据可能被知晓。例如,我的上下文(MyContext)扩展自上下文(Context),并包含用于获取字段1、字段2的方法。 - Igneous01
3
需要引用。 - spoulson
不需要引用。这是一种反模式。 - Teoman shipahi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接