简介:在使用 演化架构和紧急设计 前几期描述的技术发现 代码中的紧急设计之后,下一步您需要一 种获取和利用这些设计元素的方法。本文介绍了两种用于获取惯用模式的方法:将模式作为 APIs 进行捕 捉;使用元程序设计方法。
本 系列 的前几期主要关注紧急设计中显而易见的第一步:发现 惯用模式。发现惯用模式之后,您要 用它做什么?该问题的答案就是本期重点,本文属于由多个部分组成的系列文章的第二部分。第 1 部分 —代码与设计的关系探讨— 介绍了一种观点的理论基础,这种观点就是软件中的设计真正是指解决方案 的整个源代码。一旦转换角度将所有 代码当做实际设计,您可以开始考虑在语言级别巩固设计元素,而 非仅在图表范围和其他设计辅助项目中。在这里我要讲一下在发掘出代码中的可重用设计之后应该做些什 么,介绍获取这些模式所用的方法。我首先将它们作为简单 APIs 获取,然后描述一种可将这些元素与其 他代码区分开来的获取方法。
将模式作为 APIs 予以获取
捕捉惯用模式最简单的方式就是将它们作为自身的 API 或框架予以提取。您使用的大多数开源框架都 是与解决特定问题相关的惯用模式集。例如,Web 框架包含您构建 Web 应用程序所需的所有 API 元素, 它们预先从其他运行的 Web 应用程序中获得。例如,Spring 是用于处理依赖项注入和构建的技术惯用模 式集合,Hibernate 为对象-关系映射封装模式。
当然,您可以在您的代码中做同样的工作。这是目前为止最简单的方法,因为您改变的仅是代码的结 构(通常通过在您选择的 IDE 中重构支持)。这种方法的大量示例参见 第 1 部分 以及 “语言、表达 性与设计:第 2 部分”, 该部分探讨了设计模式。
避免结构重复
APIs 偶尔会促进结构重复。使用 APIs 会很烦人,因为您必须频繁使用主机对象来调用 API。下面来 看一下清单 1 中的示例(其中调用一个与有轨电车相关的 API):
清单 1. 访问 Car API
Car2 car = new CarImpl();
MarketingDescription desc = new MarketingDescriptionImpl();
desc.setType("Box");
desc.setSubType("Insulated");
desc.setAttribute("length", "50.5");
desc.setAttribute("ladder", "yes");
desc.setAttribute("lining type", "cork");
car.setDescription(desc);
强制用户输入主机对象(desc)会给代码增加不必要的干扰。大部分 APIs 包括主机对象并将其作为 API 的入口点,您必须携带它们才能访问 API。
目前有几个方法可缓减 APIs 中的这个问题。其中一种方法使用一个鲜为人知的 Java 语法,它允许 您通过一个匿名内部类的作用域界定 “携带” 主机对象,如清单 2 所示:
清单 2. 使用一个匿名内部类携带主机对象
MarketingDescription desc = new MarketingDescriptionImpl() {{
setType("Box");
setSubType("Insulated");
setAttribute("length", "50.5");
setAttribute("ladder", "yes");
setAttribute("lining type", "cork");
}};