怎样设计合适的接口(2)

为了解决问题,也需要由类的使用者而不是类的设计者来完成:
  class EventSourceExample{
  public void example(Event event, Handler newHandler){
  synchronized(eventSource){
  oldHandler = eventSource.getHandler(event);
  eventSource.installHandler(event, newHandler);
  }
  }
  private EventSource eventSource;
  private Handler oldHandler;
  }
  我们假设:目标对象eventSource是远程的,执行每一个方法体的时间和通讯的延迟相比是很短的。在这个例子中,eventSource的方法被调用了两次,并可能在其他的实例中重复多次,因而,开销也是至少两倍。
  此外还有一个问题是对外部的synchronized同步块的使用需求。对synchronized块的使用之所以会失败,主要因为我们通过代理对象来完成工作,所以,调用者的synchronized块,同步的是代理对象而不是最终的目标对象,调用者不可能对其行为做太多的保证。
  Combined Method必须在分布的环境,或者,线程环境中同时执行。它反映了用户直接的应用,恢复策略和一些笨拙的方法被封装到Combined Method中,并简化了接口,减少了接口中不需要的累赘。Combined Method的效果是支持一种更像事务处理风格的设计。
  在一个组合的Command-Query中提供一个单独的Query方法通常是合理的。提供分离的Command方法是不太常见的,因为Combined Method可以完成这一工作,只要调用者简单的忽略返回结果。如果返回一个结果招致一个开销的话,才可能会提供一个单独的Command方法。
  回到前一个例子中,如果installHandler method返回上一次安装的句柄,则设计变得更加简单和独立:
  interface EventSource{
  Handler installHandler(Event event, Handler newHandler);
  }
  客户代码如下:
  class EventSourceExample{
  public void example(Event event, Handler newHandler){
  oldHandler = eventSource.installHandler(event, newHandler);
  }
  private EventSource eventSource;
  private Handler oldHandler;
  }
  这样,我们给调用者提供了一个更加安全的接口,并且不再需要他们解决线程的问题。从而降低了风险和代码量,将类设计的职责全部给了类设计者而不是推给用户,即使有代理对象的出现也不会影响到正确性。
  一个Combined Method可以是许多Query的集合,许多Command的集合,或者两者兼有。这样,它可能补充Command、Query方法,也可能与之相抵触。当冲突发生的时候,优先选择Combined Method会产生一个不同的正确性和适用性。
  在另一个例子中,我们考虑获得资源的情况。假设,在下面的接口中,方法acquire在资源可用前阻塞:
  interface Resource{
  boolean isAcquired();
  void acquire();
  void release();
  }
  类似于下面的代码会在一个线程系统中推荐使用:
  class ResourceExample{
  public void example(){
  boolean acquired = false;
  synchronized(resource){
  if(!resource.isAcquired())
  resource.acquire();
  else
  acquired = true;
  }
  if(!acquired)
  ...
  }
  private Resource resource;
  }
  然而,即使我们放弃可读性和易用性,这样的设计也不是一个Command-Query分离的设计。如果引入了代理,它就会失败:
  class ActualResource implements Resource {...}
  class ResourceProxy implements Resource {...}
  如果用户既可以通过ActualResource来完成工作,也可以通过ResourceProxy来完成工作,而且,ActualResource和ResourceProxy都没有处理同步,则synchronized块可能会失败。因为,既然我们可以通过代理对象ResourceProxy来完成工作,那么,调用者的synchronized块,同步的就是代理对象ResourceProxy而不是最终的目标对象ActualResource。
  一个Combined Method解决了这个问题,它使并发和间接性更加透明。
  interface Resource{
  boolean tryAcquire();
  }
  下面的代码清晰、简单并且正确:
  class ResourceExample{
  public void example(){
  if(!resource.tryAcquire())
  ...
  }
  private Resource resource;
  }
  Combined Method带来的一个结果是使一些测试和基于断言的程序设计变得十分笨拙,然而,它适合解决线程和分布问题。
  实际应用中,接口应该单一化还是复合化,要视具体情况而定。

 

 来源: www.cn.ibm.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值