【问题标题】:Providing interface for objects within objects为对象内的对象提供接口
【发布时间】:2014-06-07 07:08:43
【问题描述】:

我正在创建一个模型,就像在 MVC 中一样,它由其他对象组成。我的单个主要模型对象包含成分对象。我的问题是我应该向主模型对象询问将由成分对象实际执行的所有操作,还是应该询问成分对象并运行其操作?我可以在第一种方法中看到,主模型必须考虑其组成模块的所有操作,并将导致添加许多简单地委托给组成对象的功能。

让我用一个与我所做的非常接近的例子来解释。下面的代码是动态的,所以请忽略 c++ 语法错误(如果有)。

class Arm
{
public:

    Move(int x, int y);
}

class Robot
{
public:
    Arm leftArm;
    Arm rightArm;

    // should this function be there?
    MoveLeftArm(int x, int y)
    {
        leftArm.Move(x,y);
    }

    // and likewise this?
    MoveRightArm(int x, int y)
    {
        rightArm.Move(x,y);
    }
}

// in the view when I want to move robot arms, should I do this
robot->MoveLeftArm(x,y);
//or this
robot.leftArm.Move(x,y);

一个转储问题,但它是否应该取决于成分对象实际支持多少操作?既然我们是它,这也是门面设计模式的一个例子吗?

我的担忧:

  • 第一种方法可以将主要对象增长到非常大的对象。我们真的想要这么大的对象有这么多方法吗?
  • 这听起来像金字塔金字塔模型,其中函数沿链级联。这是气馁吗?我似乎记得那样,但我可能错了。
  • 第二种方法让外部客户端模块直接访问它的子组件,不确定这是否完全不好?

请考虑组成对象不仅仅是上面的两个机械臂,它还有更多的方法。

【问题讨论】:

  • 我投票支持第二种方法。这允许您实现像Rotate(Arm& arm) { arm.move(..); arm.move(..); } 这样的工具。你可以通过任何一只手臂。这对于集成的外观是不可能的(是的,它是一个外观)。最后,这取决于您的需求。你也可以考虑只返回手臂的必要接口(例如IMoveable),而不是整个手臂。您甚至可以使用访问器方法限制对武器的访问。

标签: c++ oop design-patterns model-view-controller facade


【解决方案1】:

我认为封装数据和行为并让每个类维护它通常会更好,这样您就不会在它们之间建立牢固的关系。
所以最好的做法是视图调用 Robot.MoveLeftArm 和 RobotMoveRightArm,而机器人是将消息发送到执行实际运动的 Arms 的那个。 这样手臂移动的调用和实现就被封装在了 Arm 中,它可以在不影响 View 的情况下改变。
还有一些选项可以让接口定义行为并让类实际实现该行为,从而在它们之间创建契约。

【讨论】:

  • 我完全同意。归根结底,它归结为"Tell, Don't Ask" 面向对象设计的哲学。
  • 谢谢,但另一方面,即使是 .net/C# 也使用像 `System.Console.WriteLine("Hello World!")' 这样的东西,这几乎是无法想象的子组件。让我想知道他们是否可以做到?
猜你喜欢
  • 2020-02-25
  • 2017-11-14
  • 1970-01-01
  • 2022-01-03
  • 2014-03-12
  • 1970-01-01
  • 1970-01-01
  • 2010-09-18
  • 2011-04-10
相关资源
最近更新 更多