【问题标题】:OOP: Which class should own a method? [closed]OOP:哪个类应该拥有一个方法? [关闭]
【发布时间】:2012-05-06 20:34:39
【问题描述】:

我无法理解类与它们的方法之间的关系。方法是对象执行的事情,还是对象完成的事情?或者这完全是一个不同的概念?

具体来说,在图书馆的软件系统中,borrow() 方法应该属于代表图书馆读者的类,还是代表读者正在借阅的项目的类?我的直觉是它应该读起来像patron.borrow(copy),像英文句子结构,subject.verb(object);但我的导师说那是错误的,我不明白为什么他会让borrow() 属于Copy 类(而且他并没有真正解释得很好)。我不是在寻找理由,但有人能解释一下正确的关系吗?

编辑:此问题已作为“离题”关闭。我不明白。软件设计问题不适合这个网站吗?

【问题讨论】:

  • 他希望它是library.loan(patron, copy) 可能吗?有很多设计可以工作。不懂就问
  • Frungi 这是一个概念,所以它完全取决于你想如何关联这些类。
  • 不不,他希望它是copy.borrowCopy(account)。而且我已经说过他没有很好地解释事情。
  • 这都是随意的,这根本不是OOP的神器,只是在宣扬他对做OOP的“正确方法”的看法。客观上,没有“正道”,只有特定人群持有的观点。正如@6502 指出的那样,OOP 不是一组高级规则,您所说的是面向对象设计,它与 OOP不同
  • @KristopherMicinski 你说得对,抱歉,这是针对 OOD 课程的。我在脑海中将 OOD 和 OOP 混为一谈。

标签: java c++ oop class-design uml


【解决方案1】:

不太确定确切的理由,但你可以这样想,如果多个病人去看医生,只有医生知道什么时候打电话给下一个病人,所以下一个方法是一部分医生的责任,虽然很容易认为下一步应该是病人的责任,因为他必须下一步,但在图书馆的书要发行时,它应该是书籍类型的责任,而不是作为书籍的赞助人(资源)知道什么时候免费。

【讨论】:

    【解决方案2】:

    主观 :) 但老实说,我会选择 Information Expert Pattern 并说类似

    library.lend(item, patron)
    

    图书馆包含有关其拥有的项目的信息(可能在其目录中)。
    图书馆将项目借给读者(它知道因为它注册了它们)

    不确定您的讲师如何看待这一点,但这是对您的场景有意义的“抽象”级别(模仿现实世界实体的软件对象)。

    【讨论】:

    • 这可能会使库类处理太多可以在其他类中完成的东西。
    • @RayCheng 没错,但这似乎比我的方式更明智,我的方式是在书上设置赞助人方法设置属性,以及我的导师的方式。
    • @RayCheng:可以说,但这是面向对象的领域。我希望将项目和赞助人之间的“基于库”的交互封装在库中(中介者模式 - 只是为了命名 :))
    • @RayCheng:也许库可以由处理不同“其他东西”的其他对象组成(虽然不确定这在实践中如何工作)。
    【解决方案3】:

    您不应将 OOP 的概念与 Java 或 C++ 之类的特定形式混淆。

    “方法是对象的属性”这一限制不是 OOP 理念的一部分,而只是某些实现的一部分,而且您发现它不能很好地扩展。

    一个“整数”对象有多少个方法?哪个更合乎逻辑...myfile.write(myint)myint.write(myfile)?对此确实没有很好的通用答案。将方法作为单个对象的一部分的想法是一种特殊情况,有时将问题与此解决方案相适应所需的弯曲可能会变得很明显,甚至接近于展示。只有当一个方法除了被处理的对象外没有参数时,这个答案才真正完全可以接受:只有在涉及单一类型时,单一调度才是一个完美的答案。

    在其他语言中,对象和方法是分开的,例如,您有文件对象、整数对象和一个方法write(myfile, myint),它描述了需要操作时要做什么......而这个方法是既不是文件的一部分,也不是整数的一部分。

    【讨论】:

    • 你是唯一提到的派遣。也许您应该在决定将方法放在哪里时扩展为什么这很重要?这可能对 OP 有用。
    【解决方案4】:

    我想它可以去任何一种方式。没有硬性规定。这个想法是逻辑上有意义的组功能。对我来说,Patron#borrow(BookCopy)BookCopy#borrow(Patron) 具有相同的意义。或者你可能有一个课程LibManager.borrow(BookCopy, Patron)

    【讨论】:

      【解决方案5】:

      正如@Ryan Fernandes 所说,借出/借阅操作不能与赞助人或书籍一起使用。它必须与某个知道图书馆所有书籍和顾客状态的班级在一起。例如,是否有针对一本书的未决保留?有多少份可用?这位赞助人是否支付了所有费用?他有资格读这本书吗?所以通常这应该在 Library 或 LibraryService 类中。

      【讨论】:

        【解决方案6】:

        你的导师是对的。好吧,事实上,他错了。我不知道。

        我的观点是,对于这样的问题,通常都没有固定的通用答案。这在很大程度上取决于在您的特定情况下最有效的方法。使用最容易编码的东西——这将是最容易维护的。而且,通过“最容易编写代码”,我建议还考虑类的预期用户(除了您的 LibraryCopyPerson 类)。

        【讨论】:

          【解决方案7】:

          方法是对象所做的事情,还是对它所做的事情?或者这完全是一个不同的概念?

          让我先澄清一下类和对象。 Class 通常用于表示特定的类别。喜欢

          1. 汽车 不是法拉利或保时捷
          2. 水果 不是香蕉或苹果

          所以,开的是法拉利,吃的是香蕉。 不是他们的班级

          它始终是一个具有属性和行为的对象。

          甚至专门处理您的案件。

          borrow() 方法是由person 的对象对book 的对象执行的操作/行为,该对象的记录由library system 本身的另一个对象保存。

          对我来说,以 OO 方式表示这一点的好方法是

          libray.borrow(new book('book title'), new person('starx'));
          

          只是为了好玩,你怎么看这个

          person starx = new person('starx');
          book title1 = new book('title1');
          library libraryname = new library('libraryname');
          libraryname.addBook(title1);
          
          if(starx.request(title1, libraryname)) {
               starx.take(library.lend(title1, starx));
          }
          

          【讨论】:

          • 我不是在问类与对象。我在问该方法应该属于 哪个 类。比如,应该是mouth.eat(banana) 还是banana(eat)
          • @Frungi,这就是我要解释的。请看更新
          • 一个人不应该借书。如果所有的副本都在图书馆了怎么办?您会为 bookingId 抛出异常或返回 null 吗?复制.借(新人('startx'));更好。
          • 然后我撤回我的投诉。 =)
          • @RayCheng 我想赞助人在检查时会拿着副本。
          【解决方案8】:

          从类中公开的公共方法是可以在实体上执行的任务。 这样类就只会封装它的行为。

          例如: 如果我说

          Computer.TurnOn()

          该方法仅适用于计算机系统。

          如果我说,

          SomeOne.TurnonComputer()

          现在某人将负责打开计算机(设置计算机的相关属性),这意味着我们没有满足封装和分散类属性的概念。

          【讨论】:

            【解决方案9】:

            先说一些通用词。

            软件构建不应该受英语语言规则或“美”之类的约束,它是工程学科。想想你的设计是否解决了问题,是否可维护,是否可测试,是否可以并行开发等等。如果您想要更正式的内容,请查看 D. L. Parnas 的“关于将系统分解为模块时使用的标准”。

            至于您的图书馆示例。想象一下你有一个库外的副本,那么它应该有borrow 方法吗?借款如何登记?您对负责数据存储的 Copy 或 Patron 类是否满意?将borrow 放入库类中看起来更合适。职责将被明确划分,您不需要了解太多关于借用来实施 Copy 和 Patron 的知识,也不需要太多关于它们的详细信息来实施 Library。

            【讨论】:

              【解决方案10】:

              OOP 的重点是创建多态函数,这些函数在每个实现中处理一组已定义的遵守特定不变量的数据。

              因此,改变对象的方法应该在该对象的类中定义。纯函数式代码存在于何处并不重要,但它可能应该存在于其输入的类型(如果它需要单个输入)或其输出上。

              在您的示例中,如果borrow 更改了copy 中的数据,那么它应该存在于那里。但是,如果您通过某本书在特定馆藏(在赞助人中,或在图书馆的馆藏中)来模拟一本书的外借状态,那么将borrow 放在持有人类上会更有意义。但是,后一种设计存在副本可能存在多个集合中的风险,因此您还需要在副本上放置一些信息(和相应的方法)。

              【讨论】:

              • 在 OP 的例子中,我猜这个方法会改变 Patron 和 Library 中的数据。所以应该有两种方法,每个类中一种:Library.lend(book, patron)Patron.loan(book)lend 将更改Library 中的必要数据并在Patron 上调用loan,这将更改Patron 中的必要数据。
              • 大声笑,不,我错过了。显然我的评论是多余的。
              【解决方案11】:

              我今天正是在考虑这个问题。我得出了这个结论:

              在适当的上下文中更有意义。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-08-25
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-03-13
                • 1970-01-01
                相关资源
                最近更新 更多