2010-06-04 87 views
1

创建继承层次结构时,我感到困惑。抽象基类应该只包含用于继承类的常用东西。但在设计时不可能知道常用的方法,领域和属性。所以我觉得自己可以将它们与分层次继承的抽象类进行分组。这就是我在做什么而不关心哪些真正的类将在哪里成为层次结构,因为我会在综合层次结构中轻松找到一个地方。而且在层次结构中找到一些不必要的抽象类也是很有可能的。设计面向对象层次结构时的问题

但我不知道这是正确的设计方式?在非完美的抽象层次结构中会出现哪些缺点。我必须给它一个明确的例子。想象棋和棋子。如果我必须定义棋子,皇后,国王等棋子。请看下面的UML图。

http://i.stack.imgur.com/1VC22.png

我分hierarcy 2滑动件和抽象类后无-滑动片,因为我相信,滑动和无滑动会需要不同的常用成员。

但我也可以把它们定向,因为有些作品可以走8个方向,有的可4个方向,有的可以到2个或3个方向。将它们分组定向导致一些新问题。他们将在哪里等级?他们会滑下课后来吗?如果可以在滑动和非滑动组下找到四个方向分组,并且我们知道它不可能由2个类继承。所以对于这种情况我必须选择接口?如果方向不会同时存在,那么可以使用抽象类。没关系,如果我再次找到新的通用分组,这将不需要2个类继承,所以我可以在方向上定义它。

在设计结束,我所有的作品可以在层次结构完美的叶节点,这将是非常好的对未来有足够的综合楼,我也不会需要层次改变的东西。

但是可以缺点创造过大型综合性层次?

可以是在自动完成IDE中可以显示哪些迷惑他人很多不必要的和奇怪的命名抽象基类?还有什么其他的缺点?

+0

认真吗?这看起来太复杂了。 – 2010-06-04 22:06:05

回答

2

方式,方法太复杂的任务。你太过分了。这意味着你将不得不用代码填充20多个类。你应该真的简化这个。

考虑属性方面(颜色,isUnderAttack)和行为(移动)想着它。在这种情况下,您只需要一个类class ChessPiece,它具有颜色属性和isUnderAttack。然后你可以使用某种形式的依赖注入。考虑这个代码是什么样子:

public class ChessPiece 
{ 
    public enum ChessPieceColor{White, Black} 
    private IChessMove behavior; 
    public ChessPiece(IChessMove behavior, ChessPieceColor color) 
    { 
     this.behavior = behavior; 
    } 
    public void Move() 
    { 
     behavior.Move(); 
    } 
} 

public interface IChessMove 
{ 
    void Move(); 
} 

public class KnightMove : IChessMove 
{ 
    public void Move() 
    { 
     // code to perform the moving. 
    } 
} 

public class Program 
{ 
    static void Main() 
    { 
     ChessPiece knight = new ChessPiece(new KnightMove(), ChessPiece.ChessPieceColor.White); 
    } 
} 

,那么只需在每个类型的代码不同IChessMove。显然你需要在这里添加更多的信息来使其实际工作,但它应该显示你应该在这里使用的模式。当许多人都有共同的行为时,每一个可能的作品都会走得太远。

+0

是的,我们可以使用持有颜色的字段,而不是单独的白色和黑色类。这也是我的想法,但在我的应用程序中,简化对我来说更重要。因此,将它们分开将会更有帮助。是的,它定义方法是非常重要的,甚至重要的是我会在方法体中做些什么。这些会导致变化的层次性。将颜色成员放到类中会导致在方法中检查块的颜色,这就是我不喜欢的。 – Freshblood 2010-06-04 23:31:18

+3

我不认为你真的了解OOP的目的。类用于分离行为,而不是对象的属性。一个白色的棋子不会像黑色的棋子那样移动。这只是他们必须检查他们何时试图捕捉一块的条件。为每件作品制作2个课程并不是简单的事情。这意味着你必须为每一部分编写两次移动代码。另外,这是一个滑坡。谁说你不应该将WhitePawn扩展到WhitePawn1,WhitePawn2,WhitePawn3等类?目前的图表在维护方面是一场噩梦。 – drharris 2010-06-04 23:53:28

+0

我不认为我很远,不了解它的目的。白色和黑色的棋子在棋盘上有不同的移动行为。但是你有点正确,并不是所有棋子都有不同的行为。例如主教,皇后,骑士和但是我将在后面添加的评估方法需要不同的方法和方法体。因此,如果不需要,生成方法不会被重写两次。它们的基类会对它们有共同的移动生成。但是棋子具有不同的行为。 – Freshblood 2010-06-05 09:46:55

1

好的......问题是,inheritacne层次结构是脆弱的 - 它们可能很容易无用,例如在您描述为您的担忧的情况下。您可以按照您的建议以多种方式设计层次结构,但请牢记Liskov替代原则,最重要的是,您不应过度使用继承。只有在必要时才使用它。你不应该仅仅因为你可以使用抽象类和继承。我不擅长下棋,但是不同颜色的棋子有不同的行为?创建继承层次结构时有一个抽象问题的着名例子。取一个圆和椭圆,哪个更抽象?当你试图让它们中的任何一个超类时,你会以僵化的设计结束。尝试了解更多关于面向对象编程的知识,并尝试仅在没有其他选择更好时才继承。

+0

块的颜色会导致不同的行为。我们可以通过定义可以保持块颜色的成员来克服它。但这不是我喜欢的。我仍然不知道这种方式的缺点是什么。即使它看起来会更简化我的app.Think我们将只定义WhitePawn或BlackPawn等部分,它对于它们的继承和层次结构没有任何重要性,因为除了真正的部分类之外,所有的层次结构都是抽象的。我是对吗? – Freshblood 2010-06-04 23:43:22

+0

我会测试任何一种方式,并会经历什么是坏的,但在尝试之前询问它可以是有益的,并节省时间。我的国际象棋引擎玩象棋,但片段甚至不是一个类,他们只是整数定义。我想进一步深入OOP并更多地简化代码并且在代码方面没有太多的代码 – Freshblood 2010-06-04 23:45:41

1

但是,如果创建过大的综合分级,会有什么缺点?

具有过于复杂模型的缺点是,它使得代码难以写入,读取和维护。

它发生虽然。第一枪很难设计。最好不要尝试。

这是测试驱动开发的目的。而是假设你需要什么,然后使用测试来充实你的需求,从而实现实现。 TDD ftw。