2

I wan't to create Actors that are tied to a World. I'm thinking of using one of the two following code fragments. Which one of these is considered the better design? By better I mean, more readable for source code maintainer, more readable for someone just reading through the code, more flexible for future adjustments, etc.

I'm sorry if a similar question has already been asked, but I don't really know what a concept like this is called in OOP.

Option 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();

Option 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();
Lukas Schmelzeisen
  • 2,934
  • 4
  • 24
  • 30
  • 2
    In any case, you've got a circular dependency between actors and worlds. Are you sure you need that? – Fred Foo Dec 03 '12 at 16:22
  • Not necessarily. Option A never stores a reference to World and in Option B the `Actor` never actually know anything about a `World`. In basic what I want is an object `World` containing a list about all `Actors` in the `World`. However it could be that circular dependencies will be needed in the future. An `Actor` might have to interact with all other `Actors`. – Lukas Schmelzeisen Dec 03 '12 at 16:25
  • But there's a circular dependency in the code. `Actor` needs to know about `World` and vice versa. That's often a bad idea. – Fred Foo Dec 03 '12 at 16:39

5 Answers5

3

As usual it is hard to tell without the full usage context, but there are surely some pros and cons to evaluate:

In the first case

  • While the world is programmed against the Actor class it could be easily decoupled to work against an interface or contract. As your code is right now you could pass an Actor's subclass and the world would never know. This has the advantage that you lower the coupling between a world and its actors.
  • You are moving the responsibility of creating actors from the world to the world's client. This may help the World class to achieve the SRP, makes it easier to run unit tests (e.g. to pass a mock object) and is more flexible for the client. On the other had, this moves the work of creating (and eventually configuring) the actor instance on the client.

In the second case you get the inverse pros and cons of the first one; the world is tightly coupled with the actor, making it harder to configure and test, but you require your client to know less about the process of creating an actor.

An alternative that you may consider is the use of a builder (if the process of a World creation is a complex one) or a factory (if you have different configurations for creating different subclasses). This can help you to keep your World class decoupled form the actors while leveraging from the client the complexities of creating it.

HTH

Community
  • 1
  • 1
Andrés Fortier
  • 1,705
  • 11
  • 12
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.

David Bullock
  • 6,112
  • 3
  • 33
  • 43
0

When in doubt on which class should contain the responsibility, I suggest you decide based on General Responsibility Assignment Software Patterns (GRASP)

Aravind Yarram
  • 78,777
  • 46
  • 231
  • 327
0
  • First thought : Factory Pattern, when creating an object is complex then another class will be defined which handle this job.

  • Second: If creation is easy then it could be a simple constructor, then you set one of it's properties by calling a method.

  • Third: If there exists an Aggregate object which is World maybe, then you can ask him to create an actor for you, it depends on your domain.

Jahan Zinedine
  • 14,616
  • 5
  • 46
  • 70
0

The only difference I really see in the two is that in B, an actor is tied to world. It is not tied to a world in A. If an actor ever needs to exist outside the context of a world, or if an actor can exist in multiple worlds, I would vote for A.

In terms of future extensiblity, you may want to consider changing the actor base class to an interface. Then anyone would be able to add their own actor classes without needing to inherit from your base.

Jeff
  • 13,943
  • 11
  • 55
  • 103