正 文

封装的变化之排序算法中的封装


www.7dspace.com  更新日期:2006-3-10 6:48:44  七度空间


  通过对比较策略的封装,以应对它的变化,显然是Stategy模式的设计。事实上,这里的排序算法也可能是变化的,例如实现二叉树排序。由于我们已经引入了“面向接口编程”的思想,我们完全可以轻易的添加一个新的类BinaryTreeSort,来实现ISort接口。对于调用方而言,ISort接口的实现,同样是一个Strategy模式。此时的类结构,完全是一个对扩展开发的状态,它完全能够适应类库调用者新需求的变化。

  再以PetShop为例,在这个项目中涉及到订单的管理,例如插入订单。考虑到访问量的关系,PetShop为订单管理提供了同步和异步的方式。显然,在实际应用中只能使用这两种方式的其中一种,并由具体的应用环境所决定。那么为了应对这样一种可能会很频繁的变化,我们仍然需要利用“封装变化”的原理,建立抽象级别的对象,也就是IOrderStrategy接口:

public interface IOrderStrategy
{
 void Insert(PetShop.Model.OrderInfo order);
}

  然后定义两个类OrderSynchronous和OrderAsynchronous。类结构如下:

  在PetShop中,由于用户随时都可能会改变插入订单的策略,因此对于业务层的订单领域对象而言,不能与具体的订单策略对象产生耦合关系。也就是说,在领域对象Order类中,不能new一个具体的订单策略对象,如下面的代码:

IOrderStrategy orderInsertStrategy = new OrderSynchronous();

  在Martin Fowler的文章《IoC容器和Dependency Injection模式》中,提出了解决这类问题的办法,他称之为依赖注入。不过由于PetShop并没有使用诸如Sping.Net等IoC容器,因此解决依赖问题,通常是利用配置文件结合反射来完成的。在领域对象Order类中,是这样实现的:

public class Order
{
 private static readonly IOrderStategy orderInsertStrategy = LoadInsertStrategy();
 private static IOrderStrategy LoadInsertStrategy()
 {
  // Look up which strategy to use from config file
  string path = ConfigurationManager.AppSettings["OrderStrategyAssembly"];
  string className = ConfigurationManager.AppSettings["OrderStrategyClass"];

  // Load the appropriate assembly and class
  return (IOrderStrategy)Assembly.Load(path).CreateInstance(className);
 }
}

  在配置文件web.config中,配置如下的Section:

<add key="OrderStrategyAssembly" value="PetShop.BLL"/>
<add key="OrderStrategyClass" value="PetShop.BLL.OrderSynchronous"/>

  这其实是一种折中的Service Locator模式。将定位并创建依赖对象的逻辑直接放到对象中,在PetShop的例子中,不失为一种好方法。毕竟在这个例子中,需要依赖注入的对象并不太多。但我们也可以认为是一种无奈的妥协的办法,一旦这种依赖注入的逻辑增多,为给程序者带来一定的麻烦,这时就需要一个专门的轻量级IoC容器了。

  写到这里,似乎已经脱离了“封装变化”的主题。但事实上我们需要明白,利用抽象的方式封装变化,固然是应对需求变化的王道,但它也仅仅能解除调用者与被调用者相对的耦合关系,只要还涉及到具体对象的创建,即使引入了工厂模式,但具体的工厂对象的创建仍然是必不可少的。那么,对于这样一些业已被封装变化的对象,我们还应该充分利用“依赖注入”的方式来彻底解除两者之间的耦合。

2页,页码:[1] [2] 

上一篇:用快捷键快速解决QQ空间的几个常见问题
下一篇:Photoshop蒙版妙用:无痕合成美女照片
封装的变化之排序算法中的封装 作者:wayfarer 来源:博客园
收藏此页】【打印】【关闭
站 内 搜 索
 

热 点 导 读
特 别 推 荐