Java设计帮助。继承和共享代码。

4

我是一个编程开发的新手,目前在进行清晰的设计方面遇到了一些困难。具体地说,我有如下场景:

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

类:Account;方法:A、B、C、G、H、I、S1、S2、S3
类:Folder;方法:A、B、C、D、E、S1、S2、S3
类:Group;方法:A、B、C、D、E、F、S1、S2、S3
类:Role;方法:A、B、C、D、E、F、S1、S2、S3

上述的方法是抽象的,也就是说可能会有不同的FooAccount和BarAccount分别实现A方法。然而,由于它们是相同实现的Foo,因此FooAccount和FooGroup也具有相同的A方法。虽然这不算太糟糕,但是还有一些S1、S2和S3方法,即使在Foo和Bar之间也是相同的实现方式,因此FooAccount和BarAccount也具有相同的S1、S2和S3方法。

当前我的设计看起来很丑陋:

接口Object1:声明A、B、C方法
接口Object2扩展自Object1:声明D、E方法
接口Object3扩展自Object2:声明F方法
接口Account扩展自Object1:声明G、H、I方法
接口Folder扩展自Object2;
接口Group扩展自Object3;
接口Role扩展自Object3;
类Helper:定义S1、S2、S3方法

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

有人能给我一些建议吗?哪种结构可能更好?我该将所有A、B、C等方法都放入一个Util类(例如FooUtil和BarUtil)中吗?

2个回答

2

您应该根据角色而不是发生情况来对接口中的方法进行分组。因此,假设ABC属于一个角色,DE属于另一个角色,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

如果你可以提取 FooBar 的公共行为,并且让 Account 成为一个泛型类(接受 FooBar),那么你也可以考虑使用泛型。


谢谢回复,但除非我弄错了,因为Account/Group只是接口,我必须在每个类中明确地编写方法A。我正在尽可能减少重复代码... - kennyg
@kennyg - 如果您有常见的方法实现,可以将它们模式化为一个抽象类,然后从中继承(请参阅“Helper”示例--您肯定可以创建更多这样的帮助器抽象基类,以提供“A”,“B”和“C”的常见实现)。但是,在您的设计中,共享围绕“Foo”和“Bar”展开(所有“Foo *”类都具有相同的“A”,所有“Bar *”类都具有相同的“A”(与“Foo *”对应项不同)),[cont.] - Attila
你应该在一个名为 Foo(也可以是 Bar)的类中实现 A 方法,并将其传递给 Account 等实现类,这些实现类将调用传递对象的 A 方法。这样,实现就足够通用,你可以轻松地创建一个名为 FooBar 的类,并正确地捕获共享代码。 - Attila

0
不要依赖继承作为减少重复代码的机制。相反,找出一种将职责分离到不同类中的方法。
FooAccount和FooGroup具有相同的方法A
这告诉我方法A的实现应该在它自己的类(FooA)中。如果让Account和Group公开方法A真的有意义,那么FooAccount.A和FooGroup.A的实现应该只是传递给FooA.A。

你能详细解释一下“透传”吗?你的意思是FooAccount.A只是调用了FooA.A吗? - kennyg
@kennyg:没错。在我看来,一个简单的方法调用并不违反DRY原则。你想要避免重复的真正逻辑将驻留在FooA.A中,因此,如果您的其他类需要为API实现此方法,它们只需将责任委托给FooA类即可。 - StriplingWarrior

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接