我不想创建与Actors
绑定的World
。我正在考虑使用以下两个代码片段之一。哪一个被认为是更好的设计?我的意思是更好,对于源代码维护者来说更具可读性,对于只是阅读代码的人来说更具可读性,对于将来调整更灵活等等。
如果已经提出类似问题,我很抱歉,但我真的不知道在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();
答案 0 :(得分:3)
像往常一样,没有完整的使用环境很难分辨,但肯定有一些优点和缺点要评估:
在第一种情况下
Actor
课程进行编程时,可以很容易地将其与interface或contract分开。正如您的代码现在可以传递Actor
的子类,世界永远不会知道。这样做的好处是可以降低世界与演员之间的耦合。World
类实现SRP,使得更容易运行单元测试(例如传递模拟对象),并且对客户端更灵活。另一方面,这推动了在客户端上创建(并最终配置)actor实例的工作。在第二种情况下,你会得到第一种情况的反面利弊;世界与演员紧密结合,使得配置和测试变得更加困难,但是您需要您的客户更少地了解创建演员的过程。
您可以考虑的替代方案是使用builder(如果World
创建的过程是复杂的过程)或factory(如果您有不同的配置)创建不同的子类)。这可以帮助您将World
类与演员分离,同时从客户端利用创建它的复杂性。
HTH
答案 1 :(得分:1)
演员是否始终只属于一个世界,并且始终是同一个世界?选项B最适合这种情况。它限制了Actor构造函数的可见性,并使用工厂方法构造实例。这样可以减少对代码客户端的承诺,这意味着您可以更灵活地更改Actor的实现。它也很适合域的语义 - 你使用你的世界来制作演员。
但是,如果一个演员可以改变世界,或同时注册到多个世界,那么你将走向选项A.
这一切都取决于您的参考文件最终需要如何结束。
答案 2 :(得分:0)
如果对哪个班级应该承担责任有疑问,我建议您根据General Responsibility Assignment Software Patterns (GRASP)
决定答案 3 :(得分:0)
首先想到:Factory Pattern,当创建一个对象很复杂时,会定义另一个处理这个工作的类。
第二:如果创建很容易,那么它可以是一个简单的构造函数,然后通过调用方法设置其中一个属性。
第三:如果存在Aggregate object也许是世界,那么你可以让他为你创建一个演员,这取决于你的领域。
答案 4 :(得分:0)
我在两者中真正看到的唯一区别是,在B中,演员与世界联系在一起。它与A中的世界无关。如果一个演员需要在一个世界的背景之外存在,或者一个演员可以存在于多个世界中,我会投票给A。
就未来的可扩展性而言,您可能需要考虑将actor基类更改为接口。然后任何人都可以添加自己的actor类,而无需从你的基础继承。