学习面向对象的思维

时间:2009-07-21 08:01:19

标签: oop

我目前正在使用C ++编写一个小型2D游戏引擎,但我现在正面临一个守护进程 - 我很擅长设计一个实际可行的“类系统”。在我的脑海中有一个封锁,使我无法看到我应该在哪里使用课堂以及我不应该在哪里。我正在阅读一篇关于引擎设计的文章,它的目的是使用'State'类来管理不同游戏条目的状态(我使用的是int)。 它还表明游戏的所有对象(不是io /视频/声音等)都来自Renderable或NonRenderable类。这很聪明。我已经知道这是一种聪明的方法 - 我的意思是,Java中的每个对象都是基类Object吗?聪明,我知道!为什么我不那样做?我需要阅读什么才能真正融入这种心态?

另一个例子。我正在参加Ruby的夏季课程(非常简单),我们应该设计一个露营地点。简单!因此,露营地是“地块”的集合,每个都有一个电量计来衡量客人消耗的电量。我的设计是三个类,一个用于露营 - 反​​过来使用Guest和Plot类的数组。我的老师建议我多上课。 WTF(!)是我的第一个想法,在哪里,什么课程?在我看来,一切都是一个阶级 - 直到我意识到,也许规范应该是一个类?现在,仪表是Plot类中的整数。

我想学习如何为我的问题提出一个面向对象的解决方案 - 而不仅仅是如何让最明显的东西进入课堂!

提示/书籍/文章/博客?

我在CS工作了两年,并且多年来一直作为业余爱好编程!我只是被卡住了 - 这使我无法创建任何更大的软件!

16 个答案:

答案 0 :(得分:21)

我个人的经验是通过Bertrand Meyer的Object Oriented Software Construction, 2nd Edition学习面向对象的软件构建。

这本书当时对我来说非常宝贵,而且仍然是我从中学到的关于面向对象编程和软件构建的一本书。

以下是它的一些优点:

  • A部分:问题中,这是一个非常好的软件质量定义。
  • B部分:面向对象的道路中,一种逻辑的,逐步搜索OO技术的方式,使读者认为调查正在进行中,就好像仍然没有已知的结果。你可能会从这部分中获得你正在寻找的心态。
  • 在本书的技术核心 C部分:面向对象技术中,您将使您的知识扎实并学习有关按合同设计,继承,通用等方面的非常有用的技术。
  • D部分:OO方法:很好地应用该方法是一种更实用的设计方法,我也觉得非常有用。例如,参见如何查找课程(22),您可以找到online

在这些部分之后,会出现更多高级主题,例如并发(30)数据库(31)

由于本书使用Eiffel语言(由作者设计),这将使您处于正确的心态并教您思考。将这些想法应用到其他或多或少的OO编程语言中会很容易。

答案 1 :(得分:13)

<强>面向对象

面向对象的编程就是要求对象做一些事情:一个看似难以正确应用的概念。

<强> Goban

考虑使用2D游戏板,比如玩Go(称为 goban )。

首先考虑完成任务所需的行为。这意味着列出对象的行为,而不是决定行为操纵的数据。例如,基本板可能具有以下行为:

  • 放一块石头。
  • 删除Go石。
  • 取下所有的石头。

对于Go的计算机版本,可以方便地关注特定区域:

  • 标记交叉点(例如,三角形,数字,字母,圆形,方形)。
  • 从标记的交叉点移除标记。
  • 删除所有标记。

请注意, goban 不需要提供一种方法来为客户提供特定交叉点处石头的引用。相反,它可以回答有关其状态的问题。例如, goban 可能会回答以下问题:

  • 在某个交叉点是否有黑色的石头?
  • 在给定的十字路口是否有白色石头?
  • 在给定的十字路口是否有标记?

goban 不负责了解游戏的状态:属于游戏的实例(具有规则)。在现实生活中,goban只是石头的舞台。

此时,我们可以为 goban 编写一个接口,而不知道底层实现将如何工作。

public interface Goban {
  public void place( Stone stone, Point point );

  public void removeStone( Point point );
  public void removeStones();

  public void place( Mark mark, Point point );

  public void removeMark( Point point );
  public void removeMarks();

  public boolean hasWhiteStone( Point point );
  public boolean hasBlackStone( Point point );
  public boolean hasMark( Point point );
}

请注意该主板如何与规则游戏完全分开。这使得 goban 可以重复用于其他游戏(涉及宝石和十字路口)。 goban 可以继承自通用接口(例如, Board 接口),但这足以解释一种根据对象进行思考的方法。

<强>封装

Goban 接口的实现不会公开其内部数据。此时,我可以请求您实现此接口,编写单元测试,并在完成后将编译的类发送给我。

我不需要知道您使用了哪些数据结构。我可以使用你的实现来玩(并描绘)一个Goban。这是许多项目出错的关键点。许多项目编写以下代码:

public class Person {
  private HairColour hairColour = new HairColour( Colour.BROWN );

  public Person() {
  }

  public HairColour getHairColour() {
    return hairColour;
  }

  public void setHairColour( HairColour hairColour ) {
    this.hairColour = hairColour;
  }
}

这是无效的封装。考虑鲍勃不喜欢将头发染成粉红色的情况。我们可以做到以下几点:

public class HairTrickster {
  public static void main( String args[] ) {
    Person bob = new Person();
    HairColour hc = bob.getHairColour();
    hc.dye( Colour.PINK );
  }
}
鲍勃现在的头发是粉红色的,没有什么能阻止它。有办法避免这种情况,但人们不这样做。相反,封装被打破,导致僵硬,不灵活,错误缠身,不可维护的系统。

实施封装的一种可能方法是返回HairColour的克隆。修改后的Person类现在很难将头发颜色更改为Pink。

public class Person {
  private HairColour hairColour = new HairColour( Colour.BROWN );

  public Person() {
  }

  public HairColour getHairColour() {
    return hairColour.clone();
  }

  public void setHairColour( HairColour hairColour ) {
    if( !hairColour.equals( Colour.PINK ) {
      this.hairColour = hairColour;
    }
  }
}
鲍勃可以安然入睡,因为他知道自己不会醒来做粉红染色工作。

答案 2 :(得分:9)

值得记住: OO本身并不是目的。 OO的目的是让开发,尤其是代码的维护更容易在生命周期内完成。产品。谨防“OO为OO着想”的心态。

答案 3 :(得分:6)

Head First Object-Oriented Analysis and Design

我喜欢Head First Books,因为它们阅读起来很有趣。他们有练习和谜题来划伤你的头脑。我读过这本书并发现它非常好。

这本书包括:

  • 使用OO原则(封装和委托)
  • 开放式原则(OCP)
  • 单一责任原则(SRP)
  • 设计模式,UML,用例等。

答案 4 :(得分:4)

  

在我的脑海中有一个封锁使我无法看到我应该在哪里使用课程以及我不应该在哪里。

归根结底,类是将复杂系统分成彼此交互的简单部分的一种方法。尝试创建类,否则你会重复自己。

  

现在规格是Plot类中的整数。

量表是否需要成为一个班级?把它变成课堂的好处是什么?这些是你总是需要问自己的事情。

  1. 游戏引擎很难设计。这种模糊定义的要求的分离是一个复杂的过程,请阅读:article on game engines
  2. 设计是迭代的,你会多次重构,不要对此感到惊讶。

答案 5 :(得分:3)

杰夫·贝的书“ThoughtWorks Anthology”中有一篇文章:“对象健美操”,他提出了一套设计OOP软件的规则:

  1. 每种方法仅使用一个级别的缩进
  2. 请勿使用else关键字
  3. 包装所有基元和字符串
  4. 每行仅使用一个点
  5. 不要缩写
  6. 保持所有实体不变
  7. 不要使用任何具有两个以上实例变量的类
  8. 使用一流的藏品
  9. 不要使用任何getter / setters / properties
  10. 首先看,它可能看起来太严格,无法遵循所有这些规则。请记住,即使尝试编写一些能够解决这些问题的代码,也会让你成为更好的OOP设计师。

答案 6 :(得分:2)

请记住,问题从来没有一个解决方案。 将一切变成一个类也不是解决方案。特别小的东西(比如规格)很可能就像你一样在剧情类里面是一个int或float成员。

我的建议是练习是一位好老师。继续尝试,继续阅读。及时你会越来越流利。

答案 7 :(得分:2)

我可能从Craig Larman的Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development了解了面向对象软件开发的大部分内容。

在他的方法中,类是从用例系统地导出的:

  • 用例中的名词映射到类
  • 动词到方法和
  • 成员变量的形容词。

当然,对于问题域中的概念,这比GUI小部件更有效。然而,从要编写的程序的描述/用例开始,帮助我找到比忽略该步骤更好的抽象。

答案 8 :(得分:2)

对我来说,在我读了一本关于设计模式的书之前,OO没有“点击”。如果你已经对抽象类,接口等概念感到满意,那只是成功的一半。

下一步是弄清楚为什么你应该更喜欢组合而不是继承,如何编写接口以及如何编写类以便它们被解耦和良好封装。设计模式向您展示常见OO问题的解决方案,并帮助您构建符合上述准则的代码。

我不推荐任何关于C ++的特定书籍,但GOF book是设计模式(Java)的标准。我更喜欢用特定语言谈论设计模式的书籍,以便您可以获得具体的代码示例。 Design Patterns In Ruby非常好,PHP: Objects, Patterns and Practice也是如此。

我觉得你的导师并不特别知道他在说什么。 “更多课程”本身就是毫无用处的建议。

答案 9 :(得分:2)

也许你会发现Bruce Eckel的Thinking in patterns很有用。您可以从他的网站免费下载这本书(我只能发布一个链接作为新成员,所以只需点击那里的链接,你就可以找到它)。虽然这本书是从2003年开始的,但也许本书中提出的想法可以帮助你成长为一般的程序员。

答案 10 :(得分:1)

写一个非常庞大的软件,在整个过程中,它变得越大,你需要的扩展性越多,你需要的课程设计就越多,因此下次你会提前思考并制作你的软件。班级设计一开始就很好......

答案 11 :(得分:1)

一种简单的方法来提出一组合理的东西,这些东西可能应该是对象(因此也就是类):写下你的任务的问题描述,如:

在露营地有客人,每位客人都可以使用几个商店。该    软件应该能够管理每个客人消耗的功率,所以它应该知道    客人使用的商店和每个商店消耗的电力。

现在,创建一个包含所有名词的列表,以便了解问题涉及哪些类(=对象类型):

  • 露营地
  • 访客
  • 出口
  • 电源

这不一定是明确的清单,但这是一个良好的开端。

答案 12 :(得分:1)

有助于进入OO思维模式的一件事,以及早期帖子概述的实践,是重写/改进您使用OO原则编写的现有代码。

例如:

一个。在有很多if / else结构的情况下可能 您可以考虑使用类层次结构来相应地分配分支代码, 并使用多态性。

湾任何使用像(Java中的instanceof)这样的运算符都表示编程 具体的类型,你可以想一下如何摆脱支票的实例。

℃。使用“德米特定律”作为指导,看看是否有耦合 班级很高

在某种程度上,“测试驱动开发”的实践也对我有所帮助 因为它迫使你在接口/行为方面进行思考 通过一个阶级,而不是只专注于如何最好地解决问题 可以编码。

答案 13 :(得分:0)

哈哈。我记得那一点。整个“这件事怎么会起作用?”。只要保持它,在某些时候它只是点击。它真的就像一个灯泡在继续。有一刻它真的没有意义,然后一瞬间你就会在课堂上编写所有内容。

尝试下载最终可能会使用的一些开源工具并阅读代码。它会为你提供一些参考代码风格的东西。

答案 14 :(得分:0)

几年前,彼得·科德和艾德·戈登写了一本关于它的书。虽然没有填充新的过度使用的方法论,this book为对象风格的思考提供了良好的基础。

答案 15 :(得分:0)

在我看来,我读过的用于学习面向对象概念的最好的书之一是:

The Object-Oriented Thought Process

对我来说,这本书真的让你以面向对象的方式思考(好吧,标题中的线索!:)它是相当语言无关的,在VB.NET,C#和Java中包含一些小代码示例。经常引用OO分析和设计领域的许多“伟人”,如Grady BoochMartin Fowler和其他人。

由于本书可以帮助您以面向对象的方式思考,因此它通常会采用一个具体的例子,并显示OO处理问题的方式与程序方式之间的差异。如果您来自更多或程序背景,这可能是一个很大的帮助。它还触及UML之类的东西,以帮助解释和理解完整的类库(例如框架)背后的设计和类之间的交互,以及使用聚合和组合等概念设计丰富的类层次结构。