2

我不想创建ActorsWorld. 我正在考虑使用以下两个代码片段之一。其中哪一个被认为是更好的设计?更好的意思是,对于源代码维护者来说更具可读性,对于只是阅读代码的人来说更具可读性,对于未来的调整更加灵活,等等。

如果已经问过类似的问题,我很抱歉,但我真的不知道在 OOP 中这样的概念是什么。

选项 A:

// declaration:
class World {
    public:
        RegisterActor(Actor* a);
};

class Actor {
    public:
        Actor(World& w) {
            w.RegisterActor(this);
        }
        foo();
};

// usage:
World myWorld;
Actor myActor(myWorld);
myActor.foo();

选项 B:

// delcaration:
class Actor;

class World {
    public:
        Actor& CreateActor();
}

class Actor {
    friend class World;
    public:
        foo();
    private:
        Actor();
};

// usage:
World myWorld;
Actor& myActor = myWorld.CreateActor();
myActor.foo();
4

5 回答 5

3

像往常一样,如果没有完整的使用上下文很难判断,但肯定有一些优点和缺点需要评估:

在第一种情况下

  • 虽然世界是针对Actor类进行编程的,但它可以很容易地解耦以针对接口合同工作。正如您现在的代码一样,您可以传递Actor' 的子类,而世界永远不会知道。这样做的好处是可以降低世界与其参与者之间的耦合。
  • 您正在将创建演员的责任从世界转移到世界的客户身上。这可能有助于World类实现SRP,使运行单元测试更容易(例如传递模拟对象)并且对客户端更灵活。另一方面,这移动了在客户端上创建(并最终配置)actor 实例的工作。

在第二种情况下,您会得到第一种情况的相反利弊;世界与actor紧密耦合,使得配置和测试变得更加困难,但是您需要您的客户对创建actor的过程了解较少。

您可以考虑的另一种选择是使用构建器(如果World创建过程很复杂)或工厂(如果您有不同的配置来创建不同的子类)。这可以帮助您保持您的World类与参与者分离,同时利用客户端创建它的复杂性。

高温高压

于 2012-12-03T16:37:24.343 回答
1

Does an Actor only ever belong to exactly one world at all times, and always the same one? Option B fits the situation best. It limits the visibility of the Actor constructor and uses a factory method to construct instances. That makes fewer commitments to clients of your code, and that means you have more flexibility to change the implementation of Actor. It also fits the semantics of the domain pretty well - you use your World to make Actor.

However, if an Actor could change worlds, or be registered to more than one world at the same time, then you're heading towards Option A.

It all depends on how your references need to end up.

于 2012-12-03T16:41:09.283 回答
0

我在两者中真正看到的唯一区别是,在 B 中,演员与世界联系在一起。它与 A 中的世界无关。如果一个演员需要存在于一个世界的上下文之外,或者如果一个演员可以存在于多个世界中,我会投票给 A。

就未来的可扩展性而言,您可能需要考虑将参与者基类更改为接口。然后任何人都可以添加自己的演员类,而无需从您的基础继承。

于 2012-12-03T16:40:59.113 回答
0
  • 首先想到:工厂模式,当创建一个对象很复杂时,将定义另一个类来处理这个工作。

  • 第二:如果创建很容易,那么它可以是一个简单的构造函数,然后通过调用方法来设置它的一个属性。

  • 第三:如果存在一个聚合对象,可能是世界,那么你可以让他为你创建一个演员,这取决于你的领域。

于 2012-12-03T16:36:30.707 回答
0

当对哪个类应该包含责任有疑问时,我建议您根据通用责任分配软件模式(GRASP)来决定

于 2012-12-03T16:28:54.250 回答