我有一个表示水果的枚举类:
public enum Fruit{
   //实例个数不会太多
   APPLE,ORANGE,MANGO;
}
现在我需要三个接口(只是举例,可能更多)用来获取水果的信息,现有两种设计:
第一种:
提供一个类FruitInfo,提供三个方法,每一个根据传入的水果类型来进行不同的处理: public class FruitInfo{
   public String getShape(Fruit fruit){
     //下边的代码则是根据不同的fruit返回不同的形状
   }
   public String getColor(Fruit fruit){
     //下边的代码则是根据不同的fruit返回不同的颜色
   }
    public String getPrice(Fruit fruit){
     //下边的代码则是根据不同的fruit返回不同的价格
   }
第二种:
提供一个接口FruitInfo,它有三个方法分别是getShape(),getColor(),getPrice()
然后它有三个实现类分别为AppleInfo,OrangeInfo,MangoInfo分别实现了各自获取信息的方法。
然后提供一个工厂类FruitFactory,它会根据传入的Fruit来产生不同的对象,客户端只要得到对象调用对应的方法就行了:
   public FruitInfo getFruit(Fruit fruit){
     //下边是根据不同的fruit产生不同的FruitInfo对象的代码
   }----------------------分割线-------------------------
好了,上述场景我已说清楚了,现在请各位帮我分析哪种方案比较好,好在哪。我认为第二种好,因为用到了工厂模式...
但我又说不上来具体好在哪,因为如果以后增加了一种新的水果类,两种方案增加的代码量都差不多,而且访问接口的客户端改动的也不都多,只是传新的Fruit对象罢了。
唯一能想到的就是"类的单一职责原则",第一种方案类的职责太多。但是如果Fruit基本上只有那几个固定的对象,我想差别也不大。
请各位帮忙分析一下,多谢啦。

解决方案 »

  1.   

    枚举类型略去,直接将FruitInfo的那些职责加到Fruit上,就更简单点了。
    扩展的时候直接给出新的子类就OK了。
      

  2.   

    嗯,是简单了些,但会导致Fruit类太乱
      

  3.   

    那你那个 Fruit 应该叫 FruitName
      

  4.   

    Fruit类如果不需要记忆自己的Color/Shape/Price,它又需要干什么呢?
      

  5.   

    我的看法和一楼一样,直接定义Fruit类,然后用第一种方法。这样简单多了,只要存储时分好包处理就是了。
      

  6.   

    这样啊,我想想...
    我的第二种方案其实就是magong所说的做法,AppleInfo,OrangeInfo,MangoInfo其实就是三种水果,它们记忆了自己的状态。
    只不过我还做了一个工厂类用于产生所需的对象,这样客户端不需要参与创建对象,一定程度上解耦了。
    而在这样的情况下,枚举类的好处就是总是传递合法值,客户端的调用也清晰了一点。
    我说的有没有道理呢?
      

  7.   

    你这个枚举类型意义不大,你想,你要是追加一种新的水果,你就要修改一次枚举类型
    所以一个水果Fruit接口,提供你说的方法,然后水果子类实现该接口就好了
    至于工厂,就看你想怎么做了,按照一般的框架模式来分析的话,是用反射的方式比较好,所以就看你是如何管理这些类,如果是配置文件,需要传入一个配置文件的水果分类的id,如果是用名字,就直接反射

    interface Fruit { //这里用接口还是抽象类,根据具体需求决定
        public String getShape();
        public String getColor();
        public String getPrice();
    }class Apple implements Fruit {}class Orange implements Fruit {}class Mango implements Fruit {}class FruitFactory {
        public static Fruit getFruit(String id) {
            String className = Config.getFruit(id); //Config是相当于一个配置文件类
             return (Fruit)Class.forName(className).newInstance(); 
            //如果传入的id就是水果类名,直接Class.forName(id).newInstance();
        }
    }
      

  8.   


    话不能这么说啊,楼主,设计模式要看到它真的有用的时候你采用的。
    工厂模式什么时候用的?
    就是在你的初始化工作很麻烦的时候用的,比如说你的初始化要查询数据库,要查配置文件的时候,为了简化代码量,把相同代码写在工厂的create()方法里,这才是工厂模式意义所在啊,楼主不要人云亦云啊(可能措辞有点冲,冒犯楼主的地方,请见谅)
      

  9.   


    public class FruitInfo{
    //get,set
    private Fruit fruit; public String getShape(){
    //下边的代码则是根据不同的fruit返回不同的形状
    }
    public String getColor(){
    //下边的代码则是根据不同的fruit返回不同的颜色
    }
    public String getPrice(){
    //下边的代码则是根据不同的fruit返回不同的价格

    }
     public FruitInfo getFruit(Fruit fruit){
         //下边是根据不同的fruit产生不同的FruitInfo对象的代码
     }
    首先表示我认识楼主所说的两种方式并不冲突。
    如果是我的话就会修改成上面的。
    在某一个类会提供一个getFruit返回FruitInfo对象。具体的操作则可以调用具体的方法。
    但是一个FruitInfo对象对应一个Fruit对象。
    getShape,getColor,getPrice三个方法都是FruitInfo的职责。
    这里把它分成三个细粒度的方法会非常好,便宜组装和扩展。