模板方法模式实现探讨(1)

发表于:2007-06-12来源:作者:点击数: 标签:
模板方法(Template Method)模式是GOF设计模式中最为常见几个模式之一。现在流行的很多框架中(如Spring,Struts等),我们都可以看到模板方法模式的广泛应用。模板方法模式主要应用于框架设计中,在日常的应用设计中也被经常使用。可是,我们在运用模板方法模

模板方法(Template Method)模式是GOF设计模式中最为常见几个模式之一。现在流行的很多框架中(如Spring,Struts等),我们都可以看到模板方法模式的广泛应用。模板方法模式主要应用于框架设计中,在日常的应用设计中也被经常使用。可是,我们在运用模板方法模式来解决我们的需求而进行设计时,往往忽略了一些非常重要的细节。保证架构逻辑的正常执行,不被子类破坏;怎么让子类扩展模板方法等。

模板方法设计模式的意图



通常我们会遇到这样的一个问题:我们知道一个算法所需的关键步骤,并确定了这些步骤的执行顺序。但是某些步骤的具体实现是未知的,或者说某些步骤的实现与具体的环境相关。

模板方法模式把我们不知道具体实现的步骤封装成抽象方法,提供一个按正确顺序调用它们的具体方法(这些具体方法统称为“模板方法”),这样构成一个抽象基类。子类通过继承这个抽象基类去实现各个步骤的抽象方法,而工作流程却由父类控制。

考虑一个简单的订单处理需求:一个客户可以在一个订货单中订购多个货物(也称为订货单项目),货物的销售价是根据货物的进货价进行计算的(不同货物有不同的售价计算方法)。有些货物可以打折的,有些是不可以打折的。每一个客户都有一个信用额度,每张订单的总金额不能超出该客户的信用额度。

根据上面的业务,我们可以知道处理一个订单所需要的步骤:



1.遍历订货单的订货单项目列表,累加所有货物的总价格(根据订货单项目计算出销售价);

2.根据客户号获得客户的信用额度;

3.把客户号,订单的总价格,及订单项目列表写入到数据库

但是我们并不能确定怎么计算出货物的销售价,怎样根据客户号获得客户的信用额度及把订单信息写入数据库这些方法的具体实现。



所以用一个抽象类AbstractOrder确定订单处理的逻辑,把不能确定的方法定义为抽象方法,由子类去完成具体的实现。

public abstract class AbstractOrder ...{

public Order placeOrder(int customerId , List orderItemList)...{

int total = 0;

for(int i = 0; i < orderItemList.size();i++)...{

OrderItem orderItem = (OrderItem)orderItemList.get(i);

total += getOrderItemPrice(orderItem) * orderItem.getQuantity();

}

if(total > getSpendingLimit(customerId))...{

throw new BusinessException(“超出信用额度” + getSpendingLimit(customerId));

}

int orderId = saveOrder(customerId, total, orderItemList);

return new OrderImpl(orderId,total);

}

public abstract int getOrderItemPrice(OrderItem orderItem);

public abstract int getSpendingLimit(int customerId);

public abstract int saveOrder(int customerId, int total, List orderItemList);

}

AbstractOrder在placeOrder方法中确定了定单处理的逻辑,placeOrder方法也称为模板方法。在placeOrder中调用了三个抽象方法。子类只需要去实现三个抽象方法,而无需要去关心定单处理的逻辑。

模板方法模式定义及结构

模板方法模式属于行为模式的一种(GOF95)。准备一个抽象类,定义一个操作中的算法的骨架,将一些步骤声明为抽象方法迫使子类去实现。不同的子类可以以不同的方式实现这些抽象方法。

模板方法模式的静态结构图如下 :

在模板方法模式中有两个参与者进行协作。



抽象模板类:定义一个或多个抽象操作,由子类去实现。这些操作称为基本操作。



定义并实现一个具体操作,这个具体操作通过调用基本操作确定顶级逻辑。这个具体操作称为模板方法。



具体类:实现抽象模板类所定义的抽象操作。



如上面的订单处理所示,AbstractOrder就是抽象模板类,placeOrder即是抽象模板方法。getOrderItemPrice,getSpendingLimit和saveOrder三个抽象方法为基本操作。



具体子类能过需要去实现这三个抽象方法。不同的子类可能有着不同的实现方式。

Public class ConcreteOrder extends AbstractOrder...{

public int getOrderItemPrice(OrderItem orderItem)...{

//计算货物的售价

……

}

public int getSpendingLimit(int customerId)...{

//读取客户的信用额度

…..

}

public int saveOrder(int customerId, int total, List orderItemList)...{

//写入数据库

……

}

}

ConcreteOrder为AbstractOrder的具体子类,ConcreteOrder需要去完成具体的三个基本操作。同时它也具有了父类一样的处理逻辑。把具体的实现延迟到了子类去实现,这就是模板方法模式的关键。


共3页: 1 [2] [3] 下一页

原文转自:http://www.ltesting.net

...