7.模板方法模式与策略模式
模板方法模式与策略模式的作用十分类似,有时可以用策略模式替代模板方法模式。模板方法模式通过继承来实现代码复用,而策略模式使用委托。委托比继承具有更大的灵活性。继承却经常被错误的滥用。
策略模式把不确定的行为集中到一个接口中,并在主类委托这个接口。
思考上面的订单处理例子,改为策略模式后的代码如下。
把不确定的行为集中抽取到一个接口OrderHelper。
这个具体类委托这个接口的相应方法来实现具体的逻辑。Public interface OrderHelper...{ public int getOrderItemPrice(OrderItem orderItem); public int getSpendingLimit(int customerId); public int saveOrder(int customerId, int total, List orderItemList); }
这样Order类不再是一个抽象类,而是一个具体类。Order类委托OrderHelpher接口来完成placeOrder方法所需的基本操作。public class Order ...{ private OrderHelper orderHelpr; public void setOrderHelper(OrderHelper orderHelper)...{ this.orderHelper = orderHelper; } 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 += orderHelpr .getOrderItemPrice(orderItem) * orderItem.getQuantity(); } if(total > orderHelpr .getSpendingLimit(customerId))...{ throw new BusinessException(“超出信用额度” + orderHelpr .getSpendingLimit(customerId)); } int orderId = orderHelpr .saveOrder(customerId, total, orderItemList); return new OrderImpl(orderId,total); } }
像在这种情况下使用策略模式更具有优势,策略模式不需要继承来实现。而是通过一个委托对象来实现。OrderHelper接口无需要去继承任何指定的类。而相对来说,采用策略来实现会更复杂一些。
由此可见,模板方法模式主要应用于框架设计中,以确保基类控制处理流程的逻辑顺序(如框架的初始化)。像上面的测试基类中,框架通常需要控制反转。而在下面一些情况中,优级先考虑使用策略模式:
当需要变化的操作非常多时,采用策略模式把这些操作抽取到一个接口。
当那些基本操作的实现需要与其它类相关时,应该使用策略模式。通过委托接口把行为与实现完全分离出来(比如数据存取)。
比如订单处理的saveOrder方法,是写入数据库的。它的实现与你采用何种持久化方案相关。
当某些基本操作的实现可能需要在运行时改变时,可以通过在运行时改变委托对象来实现,而继承则不能。所以采用策略模式。