无需子类继承减少代码重复

Reduce code duplication without subclass inheritance

我正在研究子类化、接口和组合。当涉及到代码重复时,我最终对一些事情感到困惑。众所周知,在很多情况下,子类化和继承并不是可行的方法,但它在减少代码重复方面是有效的。

接口很强大,如果操作得当,可读性也很好,但我无法理解这样一个事实,即它确实无法帮助我减少代码重复。我们可能会在子类化无效的情况下结束。但是扩展程序的可能性很大,每当我们这样做时,试图维护开放封闭原则,我们最终会以荒谬的副本数量进行接口的实现/实现粘贴代码,它可能可以通过子类化避免(就代码重复而言)。

我们如何通过接口和组合构建出色的策略,避免一遍又一遍地编写相同的方法?这样我们就可以在保持模块化的同时坚持开放封闭的原则。我们是否有任何指导方针可以帮助我们快速有效地决定代码重复是否值得?

干杯

< /wallOfText>

我觉得这个问题很有趣,因为我们大多数人没有足够的时间阅读和重新阅读我们可以继承的所有 类,这可能导致我们编写非常低效的代码,有时"reinvent the wheel" 这最终会比我们查看其他 类.

花费更多的时间

我解决这个问题的建议是创建微服务,执行特殊工作的小型迷你应用程序,这样你就不必像现在这样频繁地使用继承,而且你会知道你的确切输出得到。此外,您还可以在其他应用中重复使用这些 "microservices"。

作为旁注,查看@AntoineDubuis 推荐的书籍,我发现它们会很有帮助。

面向对象建模是非常主观的,但我在这里唯一能做的就是旧的继承与组合讨论: https://www.thoughtworks.com/insights/blog/composition-vs-inheritance-how-choose

根据您的论证,我相信您经常尝试从两个或多个具有相似代码的 class 中提取一个超级 class,这样它们就可以共享相同的继承方法,而不仅仅是复制它们。尽管从技术上讲这完全可以满足您的需求,但您还应该注意继承语义,因为它将表示 is-a 关系(即 car is-a 车辆、狗 是一种 哺乳动物、报告屏幕 是一种 只读屏幕)。由于 Java 不提供多重继承,如果你 class 层次结构增长,你可能最终会变得有限和困惑。

因此,在开始提取超级classes 以供重用之前,请记住您还可以提取此 code-i-want-to-reuse 单元以是 其他 class 的一部分(组合)。

抱歉我的概念示例,但这里是狮子都是哺乳动物和猎人。他们自然应该继承Mammals superclass(在哺乳动物中有很多可重用的代码)。由于并非所有哺乳动物都会捕猎,我们不想在 Mammals class.[=13 上定义新的 hunt() 方法=]

此时,您可能正在考虑创建一个新的继承级别:哺乳动物 <- 狩猎哺乳动物。但是想一想:如果您继续对动物的每个独特方面都这样做,您将在一个棘手且令人困惑的层次结构中拥有数十个 classes。除此之外,我们还知道一些爬行动物和鸟类也会捕食,所以,我们最好将所有狩猎的东西隔离在别处。

作为继承的健康替代方案,我们可以定义一个单独的 Hunter class。要重用它的内容,我们需要做的就是将一个 Hunter 对象作为 DogLion[=53 的成员=](一个字段)。如果我们需要把狗和狮子一起当作猎人(多态),我们可以定义一个CanHunt接口来对它们进行分组。

检查下面的例子:

class Hunter {
   void hunt(){
       System.out.println("i'm hunting...");
   }
}

interface CanHunt{
   Hunter getHunter();
}

class Dog extends Mammals implements CanHunt{
   ...
   Hunter hunter = new Hunter();
   
   @Override
   Hunter getHunter(){
       return hunter;
   }      
   ...
}


class Lion extends Mammals implements CanHunt{
   ...
   Hunter hunter = new Hunter();
   
   @Override
   Hunter getHunter(){
       return hunter;
   }      
   ...
}

这里我们有一个多态示例代码,它要求狗和狮子做他们的狩猎活动:

...
List<CanHunt> hunters = new LinkedList();
hunters.add(new Dog());
hunters.add(new Lion());

for(CanHunt h:hunters){
  h.getHunter().hunt(); //we don't know if it's a dog or a lion here...
}
...

希望这个简单的例子能给你一些启发。如果我们不断将其发展为更详细但更灵活的设计,它可能会变得非常复杂。例如,Hunter class 可以是抽象的,具有不同的实现,因为狗的捕猎方式与狮子不同,但它们有一些共同的行为。