[Study Note] Patterns in Practice 20100402
这一系列文章是 Jeremy Miller 在 MSDN Magazine 上从 June, 2008 开始的一个专栏,大概是每两个月一篇吧。其中 2008 年的四篇文章关注一些 software design fundamentals 基本的设计理念,学习一下。
Agile Software Development Principles, Patterns, and Practices. Robert C. Martin
software entities should be open for extension but closed for modification
Single Responsibilty Principle
a class should have one, and only one reason to change
在这里 Miller 举了一个可怕的例子,busy class—— OrderProcessingModule,做了几乎所有需要的事情:从配置文件获取连接字符串 grabbing configuration file information;从数据库获得订单实例 doing data access;更新订单,处理国际订单,判断订单大小并调用不同的处理函数 running business rules for order processing;最后,如果订单已经准备好了,那么发货 transforming completed orders into shipments……
An easy way to follow the Sigle Responsibility Principle is to constantly ask yourself whether every method and operation of a class is directly related to the name of that class.
The Chain of Responsibility Pattern
我在看到这段文章之前,一直没有想明白如何替换代码中过多的 if…else.. 或者是 switch 代码段落,虽然知道这是属于坏味道的一种。
其实之前上课的时候曾经听到这部分的内容,看书的时候也见到类似的代码,但是却一直没有把这些联系起来。非常简单的就是,你只需要增加一个 Interface
public interface IOrderHandler
{
void ProcessOrder(Order order);
bool CanProcess(Order order);
}
然后就可以把业务逻辑中的那些条件分支,分别放置那些实现了这个接口的类里面,然后在 OrderProcessingModule 中采用 constructor injection 的方式(我不知道这样说对不对)调用。
public class OrderProcessingModule
{
private IOrderHandler[] _handlers;
public OrderProcessingModule()
{
_handlers = new IOrderHandler[]
{
new InternationalOrderHandler(),
new SmallDomesticOrderHandler(),
new LargeDomesticOrderHandler(),
}
}
public void Process(OrderStatusMessage orderStatusMessage, Order order)
{
updateTheOrder(order);
IOrderHandler handler = Array.Find(_handlers, h => h.CanProcess(order));
handler.ProcessOrder(order);
}
…
}
这里的代码并不完整,不过有点奇怪为什么 _handlers 设置为 IOrderHandler[] 而不是 List<IOrderHandler> ? 难道就是为了后面的 Array.Find() ? 之前还在困惑,为什么没有使用 foreach,后来才看明白在业务逻辑里面是 if…else if…else 的关系。
见识了一个新的 method —— find(),在 Array 和 List(T) 里面分别有其实现。
Double Dispatch
Miller 举了一个例子来说明什么是 Double Dispatch。假如你要让下属完成一件事情,而你并不知道具体应该如何去做;这时你打电话请教去请教某位大牛,与其让大牛给你讲解之后由你转述,那么还不如让大牛直接和你的下属去说明。
这里的例子是关于 Model View Presenter (MVP) 和 Application Controller pattern 的,之前在写一个简单的 WinForm 程序的时候,采用了丑陋的架构,真是应该提前看看这篇文章。
Liskov Substitution Principle
the most common manifestation of the Open Closed Principle is using polymorphism to substitue an existing part of application with a brand new class.
functions that use pointers on references to bass classes must be able to use objects of derived classes without knowing it.
如果简单一点的理解,就是说如果你的方法适用于某一个基类或者是接口,那么所有继承了这个基类或者接口的子类都可以适用于该方法;更进一步,我觉得 Liskov Substitution Principle 并不是要我们使用子类去替换父类/接口,而是说,亲生的兄弟姐妹(实现了同一个基类或者接口的不同子类)之间可以互相替换。
Finding Closure
the Open Closed Principle is only realized by polymorphism if a class only depends on the public contract of the other classes it interacts with.
treat the Open Closed Principle as a design vector rather than an outright goal.