有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java处理这个问题的正确设计是什么?

为了这个问题,我正在开发一个遗留Java应用程序,它处理“水果”和“蔬菜”。 它们在内部被视为不同的东西,因为它们并没有所有方法/属性的共同点,但很多事情都与它们做得非常相似

因此,我们有大量的方法,使用适当的方法,即使用适当的方法。这些都非常相似,除了用水果做事情的方法只称为用水果做事情的方法,蔬菜也是一样

我想重构它以减少重复,但我不确定实现这一点的最佳方式是什么。我读过一些关于设计模式的书,但我不知道它是否让我更清楚。(我可以识别我使用的代码中的一些模式,但我真的不知道什么时候应该应用模式来改进周围的事情。也许我应该阅读更多关于重构本身的内容……)

我在考虑这两种选择:

1创建一个类,该类可以有水果或蔬菜的实例,并将其传递给方法,尽量减少重复。事情是这样的:

public void doSomething(Plant p) {
   // do the stuff that is  common, and then...
   if (p.hasFruit()) {
       doThingWithFruit(p.getFruit());
   } else {
       doThingWithVegetable(p.getVegetable());
   }
}

这会让事情变得更好,但我不知道。。。感觉还是不对

2我认为的另一种选择是在水果和蔬菜中放置一个接口,与它们共同的东西,并使用它来传递。我觉得这是一种更干净的方法,尽管我必须使用instanceof并在水果/蔬菜需要特定材料时使用

那么,我还能在这里做些什么呢?这些方法的缺点是什么

更新:请注意,这个问题有点简化,我正在寻找使用“植物”的方法,也就是说,代码主要是“使用”它们,而不是对它们进行操作。话虽如此,我提到的那些类似方法不能在“Plants”类中,它们通常还有另一个参数,比如:

public void createSomethingUsingFruit(Something s, Fruit f);
public void createSomethingUsingVegetable(Something s, Vegetable v);

也就是说,除了水果/蔬菜之外,这些方法还有其他问题,并不适用于任何水果/蔬菜类

更新2:这些方法中的大多数代码只读取水果/蔬菜对象的状态,并根据适当的类型创建其他类的实例,存储在数据库中,等等--根据我对注释中一个问题的回答,我认为这很重要


共 (2) 个答案

  1. # 1 楼答案

    我认为第二种方法会更好。。按照界面设计总是更好的设计方式。。这样,您就可以轻松地在实现之间切换

    如果使用接口,就不需要进行类型转换,因为可以轻松利用polymorphism的概念。。也就是说,基类引用将指向一个子类对象

    但是如果您想在接口中只保留fruitsvegetables通用的方法,并在实现类中保留特定的实现。。那么在这种情况下typecasting将是必需的

    因此,您可以在接口级别使用通用方法。。以及更具体的实现方法

    public interface Food {
        public void eat(Food food);
    }
    
    public class Fruit implements Food {
    
        // Can have interface reference as parameter.. But will take Fruit object    
        public void eat(Food food) {
            / ** Fruit specific task **/
        }
    }
    
    public class Vegetable implements Food {
    
        // Can have interface reference as parameter.. But will take Vegetable object
        public void eat(Food food) {
            /** Vegetable specific task **/
        }
    }
    
    public class Test {
        public static void main(String args[]) {
             Food fruit = new Fruit();
             fruit.eat(new Fruit());    // Invoke Fruit Version
    
             Food vegetable = new Vegetable();
             vegetable.eat(new Vegetable());   // Invoke vegetable version
    
        }
    }
    

    好的,我修改了一段代码,使eat()方法接受Food类型的参数。。那没什么区别。。您可以将Vegetable对象传递给Food引用

  2. # 2 楼答案

    我会创建并抽象基类(比方说-Food,但我不知道你的领域,其他的可能更适合),然后开始一个接一个地将方法迁移到它

    如果您看到“doSomThingWithVeg”和“doSomthingWithFruit”略有不同,请在基类中创建“doSomThing”方法,并使用抽象方法只做不同的部分(我猜主要业务逻辑可以统一,只有写入DB/文件等小问题是不同的)

    当你准备好一种方法时——测试它。确定没问题后,去另一个。完成后,水果和蔬菜类不应该有任何方法,而应该有抽象类的实现(它们之间的微小差异)

    希望有帮助