您的位置:首页 > 其它

类的递归和组合模式

2008-03-11 15:39 141 查看
                                                                  类的递归和组合模式
     递归算法是大家非常熟悉的一种算法。如著名的菲波拉契数列:输入数列的前两项,以后的每一项都是它的前两项之和。现在我们要求该数列的第N(N>0)位的数是多少。对于这个问题,我们可以很轻松的给出下面的算法:
 public int getResult(int first,int second,int number)
 {
   if(number==1) return first;
   else if(number==2) return second;
   else if(number>2) return getResult(first,second,number-2)+getResult(first,second,number-1);
   //输入有误,返回错误代码
   else return –1;
 }
      这就是一个典型的递归算法。这种算法的一个好处是客户端在使用该方法时,不管是N为1或2或者以上,都使用同一个方法,简化了客户端的调用。
      关于递归的话题,在这里我们也不想多说,我们却有兴趣将这个问题扩展开来说:我们知道,类其实是数据和对数据的算法放在一起的封装,既然算法有递归的问题,如上面所示;那么数据是不是也有递归的问题呢?如果答案是肯定的的话,那么该算法和数据加在一起不就是类了,那么类也应该有递归的问题了?
      真的是这样吗?
      我们来看这样一个实际的问题:
      我们会经常去买一些光盘,如果买得多的话,就会需要一个光盘盒。假设商家需要这么一个售卖系统,卖给客户商品需要打印商品信息和应付款项。
      这里我们分析一下,需要两个类:光盘类和光盘盒类。每一类都有相同的两个方法,一个打印商品信息、一个给出应付款项。
      然后我们在客户端调用如下:
      如果客户买光盘,则调用光盘类的两个方法;
      如果客户买光盘盒,则调用光盘盒类的两个方法;
      如果客户买装有光盘的光盘盒,则调用两者之和。
      以上是我们的一个常规的思路。对于这样的客户端调用,我们会发现它的很多弱点:第一是不符合依赖颠倒原则,客户端强烈的依赖两个具体的类,这样,如果商家再增加一种新的商品,则需要修改客户端;第二是将对商品的判断放在了客户端,不符合单一职责原则。
      但是我们看看客户端对两个类的调用方法,就会发现它很符合递归算法的一般逻辑,只不过这里不是简单方法,而是类。那么我们对于这样的类,也会不会有所谓的递归算法呢?
      为什么需要递归算法?我们先不考虑太多,递归算法有一个明显的好处就是客户端调用的接口是统一的,而不需要做if…else…判断,这简化了客户端的调用。
      这里所谓的类的递归,其实就是组合模式。下面我们来看看组合模式是怎么来解决上面的问题的:
      首先我们来写一个接口,这是绝大多数的模式需要做的,它是为了满足面向对象的基本原则的依赖颠倒原则,而该原则的目的是为了使用多态性:
 public interface Equipment
 {
   public void description();
   public double getCount();
 }
      这个接口有两个目的:对商品进行描述和取得应付款项。
      接着我们来看光盘类的实现:
 public class Disk implements Equipment {
  public void description() {
   System.out.println("disk...");
  }
  public double getCount() {
   return 1.2;
  }
 }
      这个类很简单,没有什么好说的。下面来看光盘盒类:
 import java.util.ArrayList;
 import java.util.List;
 
 public class Classic implements Equipment {
  private List disks = new ArrayList();
  public void add(Equipment equipment)
  {
   disks.add(equipment);
  }
  public void description() {
   //先给出对盒部分的描述
   System.out.println("classic...");
   //然后是对盘部分的描述,两者加起来就是对带盘的光盘盒的描述
   for(int i=0;ird?ld:rd)+1;
  }
 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: