php设计模式介绍之规范模式

在一个应用软件的成型过程中,一些意想不到的商业逻辑到处出现。比如,基于价格的考虑,这个任 务必须减少项目;而那个任务也因为销售税而必须选择合适的比率;而其它的任务也必须因为其他的特 别条件而终止。一些商业规则是简单的,只需要不到一两个布尔比较关系就够了,然而它的规则可能需 要费时的估计,需要查询数据库或者用户输入数据来引导。

通过书写代码可以把抽象(比如一条 商业规则)转化为具体可见的东西。但是抽象物(比如购物方式,税率,或者计算海运费等等)都有其 进化的方式,而且这些改变很容易难倒一个不幸运的开发人员。为了保证安全可靠——到目 前为止你在这本书所看到的——尽可能的分离封装那些容易改变的模块是个很完美的想法。 而且,这的确也一个明智的应对商业规则的策略。

问题描述

有没有明确的方式来封装商 业逻辑呢?有没有一个容易改写和重用的技术呢?

解决方案

规范模式是为验证和选择而 开发的:

确认一个特殊的对象是否满足一定的标准

从集合中选择出满足给定标准的元素 。

规范模式能让你有效的组织这些标准,并在你的应用程序中灵活的使用他们。

代码重 构技术已经激发你的兴趣,你决定使用它来提升代码的清晰度和重用性。规范模式通过系统化进一步的 深化了这一步,它系统把这个结构分解成一个个单独的对象,这些对象能够很方便的插入到你的应用程 序的合适地方。很多情况下,在你的应用程序里,规范对象是参数化的,而且经常被组合在一起来构建 复杂的合乎逻辑的表达式。

相关知识

Eric Evans 和 Martin Fowler 发表过一篇关于规 范模型的文章,地址是:http://www.martinfowler.com/apsupp/spec.pdf

这个模式在Eric Evans的书本《动态驱动设计》(“Domain Driven Design”)的第224到273页有详细的介绍。

为了合理的全面覆盖这个模式,这章被组织成合乎逻辑的三部分。第一部分通过一个纯粹的实例 来说明基本的模式概念。(Evans 和 Fowler 把这个称为为“硬编码规范Hard Coded Specification”)。接下来的部分演示了如何构建一个参数化规范模型,它提供了一个更加动态 和灵活的框架来实现规范模式(或者因此而称为“参数化规范”)的重用。最后一部分,我 们开发了一个“方案工厂”(Policy Factory),它把许多规范对象集中成一个易于使用的包 (package)。

Traveling to Warm Destinations(到温暖的目的地去旅行)

最近,我和我 的家人计划去度一个假期,我的妻子想去一个“温暖的地方”。虽然有无数旅行相关的站点 ,但是在我们访问过的站点中没有一个站点能够为每一个目的地提供详细的天气信息。没办法,我们不 得不转到weather.com然后开始搜索,这是十分的不方便的。现在让我们来改变这种情况,为一个假定的 旅行站点增加一个天气搜索功能。在这里我们是用规范模式这个指南来引导你编码,从而比较旅行者期 望的最低温度和许多目的地的平均温度

首先,我们创建一些非常简单的对象。第一个是旅行者( a Traveler),它存储了首选的最低温度。

// PHP5
class Traveler {
public $min_temp;
}

接下来我们创建一个对象来表示目的地(Destination)。 由于平均温度是一个关键的标准,目的地的构建函数(__constructor)应该得到一个十二维的数组,该 数组的每一个值对应一年里面每个月的平均温度。

class Destination {
protected $avg_temps;
public function __construct($avg_temps) {
$this->avg_temps = $avg_temps;
}
}

目的地(Destination)同样也还要一个方法,通过调用这 个方法能够得到这个目的地在指定月份的平均温度。

class Destination {
//...
public function getAvgTemPByMonth($month) {
$key = (int)$month - 1;
if (array_key_exists($key, $this->avg_temps)) {
return $this->avg_temps [$key];
}
}
}

最后,一次旅行(类Trip)就由一个旅行者(类 Traveler),一个目的地(类Destination)和一个日期(a Date)联合组成。

class Trip {
public $date;
public $traveler;
public $destination;
}

给出上面这些对象,你就可以通过Trip::date得到旅行的月份,并且你能够比较目的 地的月平均温度和旅行者期望的最低温度。(这个比较可能不是特别的复杂,但是你还是需要你自己亲 自去实现)

让我们看看如何用规范模式实现“温暖目的地”的商业逻辑,并且看看如 何应用这个模式来验证每一个目的地并选择出所有合适的目的地。

样本代码

规范模式的 核心是一个带有IsSatisfiedBy()方法的对象,IsSatisfiedBy()方法接收一个变量来评估并且返回一个 基于规范标准的布尔值。


“目的地是足够温暖的”的标准可能就是:

class TripRequiredTemperatureSpecification {
public function isSatisfiedBy($trip) {
$trip_temp = $trip->destination->getAvgTemPByMonth(
date(‘m’, $trip->date));
return ($trip_temp >= $trip->traveler ->min_temp);
}
}

时间: 2024-10-14 21:34:52

php设计模式介绍之规范模式的相关文章

php设计模式介绍之工厂模式

在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象 实例的.但是在一些情况下, new操作符直接生成对象会带来一些问题.举例来说, 许多类型对象的创造 需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需 要的对象之前必须先生成一些辅助功能的对象. 在这些情况, 新对象的建立就是一个 "过程 ",不仅是一个操作,像一部大机器中的一个齿轮传动. 问题 你如何能轻松方便地 建立这么" 复杂

php设计模式介绍之策略模式

在编写面向对象的代码的时,有些时候你需要一个能够自己根据不同的条件来引入不同的操作对象实 例.例如,一个菜单功能能够根据用户的"皮肤"首选项来决定是否采用水平的还是垂直的 排列形式,或者一个计费系统可以自行根据用户的收货地址来决定税率. 一般来讲,一个控制菜 单的对象实例包括了add(), delete(), 和 replace()等菜单元素:并通过set()进行配置,用render() 来管理显示模式.无论你想生成什么样子的菜单,你都可以用同一个对象类来处理.不同菜单的对象实 例只是

php设计模式介绍之迭代器模式

类中的面向对象编程封装应用逻辑.类,就是实例化的对象,每个单独的对象都有一个特定的身份和 状态.单独的对象是一种组织代码的有用方法,但通常你会处理一组对象或者集合. 属性来自 SQL 查询的一组数据就是一个集合,就像本书前面章节介绍的 Monopoly 游戏示例的对象列表. 集合不一定是均一的.图形用户界面框架中的 Window 对象可以收集任意数量的控制对象 - Menu. Slider 和 Button.并且,集合的实现可以有多种方式:PHP 数字是一个集合,但也是一个散列表,一 个链接列表

php设计模式介绍之单条模式

几乎所有面向对象的程序中,总有一两个资源被创建出来,在程序应用中持续被共享使用.例如,这 样的一个资源,在一个电子商务程序的数据库连接中使用:这个连接在应用程序启动时初始化,程序于 是可以有效的执行:当程序结束时,这个连接最终被断开并销毁.如果是你写的代码,没必要在每时每 刻创建一个数据库连接,这样非常低效.已经建立好的连接应该能被你的代码简单重复的使用.这个问 题就是,基于以上要求你将如何进行这个数据库连接?(或者连接其它被循环使用的唯一资源,比如一 个开放文件或者一个队列.) 问题 你怎样确

php设计模式介绍之注册模式

我们通常认为避免使用全局变量是一种好的选择,因此,对象经常被作为参数从一段代码传递到另一 段.但是传递实例的一个问题就是对象有时候不知道将要传递给谁--?经过一个函数后才被 传递到真正需要这个对象的函数. 为了编写,阅读,修改代码的方便,最好能够减少不同对象的 数量,并且能够将大量广泛使用的对象统一表示为一个单一,常用的对象. 问题: 你如何 通过单一的全局的对象来获取对其它对象的引用? 解决方案: "注册模式" 就像"对象的电话簿"--储存并且能够取回对对象引用的

php设计模式介绍之观测模式

一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力.当对象们连接在一起时,它 们就可以相互提供服务和信息. 通常来说,当某个对象的状态发生改变时,你仍然需要对象之间 能互相通信.但是出于各种原因,你也许并不愿意因为代码环境的改变而对代码做大的修改.也许,你 只想根据你的具体应用环境而改进通信代码.或者,你只想简单的重新构造通信代码来避免类和类之间 的相互依赖与相互从属. 问题 当一个对象的状态发生改变时,你如何通知其他对象?是 否需要一个动态方案――一个就像允许脚本的执行一样,允许自

C#设计模式(9)——装饰者模式(Decorator Pattern)

原文:C#设计模式(9)--装饰者模式(Decorator Pattern) 一.引言 在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).AccessoriesPhone(挂件手机类)等,这样就会导致 "子类爆炸"问题,为了解决这个问题,我们可以使用装饰者模式来动态地给一个对象添加额外的职责.下面让我们看看装饰者模式. 二.装饰者模式的详细介绍 2.

php设计模式之简单工厂模式详解_php技巧

本文以实例形式较为详细的介绍了PHP设计模式的简单工厂模式,对于进行PHP程序设计来说有很好的借鉴作用.具体如下: 一.概念 简单工厂模式 [静态工厂方法模式](Static Factory Method) 是类的创建模式 工厂模式的几种形态: 1.简单工厂模式(Simple Factory)又叫做 静态工厂方法模式(Static Factory Method) 2.工厂方法模式(Factory Method)又叫做 多态性工厂模式(Polymorphic Factory) 3.抽象工厂模式(A

PHP设计模式之装饰者模式代码实例

  这篇文章主要介绍了PHP设计模式之装饰者模式代码实例,装饰者模式就是不修改原类代码和继承的情况下动态扩展类的功能,本文就给出了代码实例,需要的朋友可以参考下 定义: 装饰者模式就是不修改原类代码和继承的情况下动态扩展类的功能.传统的编程模式都是子类继承父类实现方法重载,使用装饰器模式,只需添加一个新的装饰器对象,更加灵活,避免类数量和层次过多. 角色: Component(被装饰对象基类) ConcreteComponent(具体被装饰对象) Decorator(装饰者基类) Contret