【问题标题】:Java design help. Inheritance and sharing codeJava 设计帮助。继承和共享代码
【发布时间】:2012-06-19 17:21:56
【问题描述】:

我在编程开发方面仍然有点菜鸟,并且在制作干净的设计方面遇到了一些麻烦。具体来说,我有一个场景如下:

我有 4 个类,每个类都有共同的功能。让我们将这些方法称为 A、B、C 等。

类:帐户;方法:A、B、C、G、H、I、S1、S2、S3
类:文件夹;方法:A、B、C、D、E、S1、S2、S3
类:组;方法:A、B、C、D、E、F、S1、S2、S3
类:角色;方法:A、B、C、D、E、F、S1、S2、S3

上面指定的方法是抽象的。因为可能有一个 FooAccount 和一个 BarAccount 以不同的方式实现方法 A。但是 FooAccount 和 FooGroup 具有相同的方法 A(因为它们具有相同的实现;Foo)。还不错,除了有些方法 S1、S2 和 S3 甚至在 Foo 和 Bar 之间实现相同,因此 FooAccount 和 BarAccount 具有相同的方法 S1、S2 和 S3。

目前我的设计很丑:

接口 Object1: 声明 A、B、C
接口 Object2 扩展 Object1: 声明 D、E
接口 Object3 扩展 Object2: 声明 F
接口帐户扩展 Object1: 声明 G、H、I
接口文件夹扩展 Object2;
接口组扩展Object3;
接口角色扩展 Object3;
类助手:定义 S1、S2、S3

我知道禁止多重继承是有充分理由的,但如果允许我这样做,我可以将方法 S1、S2 和 S3 放入 Object1 并将所有接口转换为抽象。然后 FooAccount 可以扩展 Account 和 FooObject1。

谁能给我一些建议,看看哪种结构可能更好?我是否应该将所有 A、B、C 等放入 Util 类(例如 FooUtil 和 BarUtil)?

【问题讨论】:

    标签: java oop


    【解决方案1】:

    您应该根据角色而不是发生来对接口中的方法进行分组。所以假设A、B、C属于一个角色,D和E属于另一个角色,而F在其中

    interface Role1 - A, B, C
    interface Role2 - D, E
    interface Role3 - F
    interface Account extends Role1
    interface Folder extends Role1, Role2
    interface Group extends Role1, Role2, Role3
    

    如果你有通用的方法实现,你可以将它们移到提供默认实现的抽象基类中

    abstract class Helper - S1, S2, S3
    

    然后你可以声明你的具体类

    class FooAccount extends Helper implements Account
    

    如果您可以提取Foo 和Bar 共有的行为,并且让Account 成为泛型类(采用Foo 和Bar)而不是接口,那么您也可以考虑使用泛型

    【讨论】:

    • 感谢您的回复,但除非我弄错了,因为 Account/Group 只是接口,我必须在每个类中显式地写出方法 A。我正在尝试尽可能减少重复代码...
    • @kennyg - 如果你有通用的方法实现,你可以将它们模式化为一个抽象类,你将继承自(参见Helper 的示例——你当然可以创建更多这样的辅助抽象提供A、B 和C 的通用实现的基类。但是在您的设计中,共享围绕Foo 和Bar(所有Foo* 类具有相同的A 并且所有Bar* 类具有相同的A(这与Foo* 对应物不同) )), [续]
    • [cont.] 你应该在你传递给Account 等实现的Foo(也是Bar)类中实现A,这反过来又会调用传递的-on 对象的A 方法。这样,实现就足够通用了,您也可以很容易地想出一个FooBar 类,并且仍然可以正确捕获共享代码
    【解决方案2】:

    不要依赖继承作为减少重复代码的机制。相反,想办法将职责分离到不同的类中。

    FooAccount 和 FooGroup 具有相同的方法 A

    这告诉我方法 A 的实现属于它自己的类 (FooA)。如果Account 和Group 公开方法A 真的有意义,那么FooAccount.A 和FooGroup.A 的实现应该只是传递给FooA.A。

    【讨论】:

    • 您能更详细地了解传递的信息吗?你的意思是 FooAccount.A 只是调用 FooA.A 吗?
    • @kennyg:没错。在我看来,一个简单的方法调用并不违反 DRY 原则。您想要避免重复的真正逻辑将驻留在 FooA.A 中,因此如果您的其他类需要为您的 API 实现此方法,他们可以将责任委托给 FooA 类。
    猜你喜欢
    • 2011-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多