views:

28

answers:

3

Let's say I'm modeling a workforce of workaholics. We have Bob, who is both a plumber and a carpenter by trade. There's Jane, who is a teacher. And finally Jack, the detective, bowling-alley entrepreneur, and mad scientist.

Each position or job type can have properties or methods specific to only that job. For example, a plumber will have methods like fixLeakingSink() and properties like exposedButtCrack that a teacher will not have. But, there will be some shared properties and methods.

If my superclass is a Worker, and I am avoiding multiple inheritance, what is the best-practice way to model a scenario like this? I originally considered using the Decorator design pattern, but I'm not sure this is the correct application for it. (If knowing what language this will be implemented in is helpful, or you want to include code snippets in your explanation, it's PHP5.)

A: 

Seems pretty straight-forward.

Each job type extends Worker

Worker contains (references) a collection of job instances.

Job has no inheritance relationship to anything (Unless you want to add more information to the problem).

Bill K
+1  A: 

I would probably use composition and have a Worker who has a collection of Jobs. Each job might have a common interface, but could also include it's own methods. Decorator doesn't really apply here as it assumes a common interface in which you build up the implementation of that single interface. Using composition would allow you to a common Worker with the flexibility to have any number of possible Jobs of various types.

C# implementation:

public interface IWorker
{
    void AddJob( Job job );
    void RemoveJob( Job job );
    void SetCurrentJob( Job job );
    Job GetCurrentJob();
}

public interface IJob
{
    void Work();
}

public class Worker : IWorker
{
    private List<Job> Jobs { get; set; }

    private int CurrentJob { get; set; }

    public Worker()
    {
        this.Jobs = new List<Job>();
        this.CurrentJob = -1;
    }

    public void AddJob( Job job )
    {
       this.Jobs.Add( job );
    }
    public void RemoveJob( Job job ) { ... }
    public void SetCurrentJob( Job job ) { ... }
    public Job GetCurrentJob()
    {
        return this.CurrentJob > 0 ? this.Jobs[this.CurrentJob] : null;
    }
}

public class Bartender : IJob
{
    public Work()
    {
        this.OpenBar();
        this.TendBar();
        this.Close();
        this.CleanUp();
    }

    public void OpenBar() { ... }
    public void TendBar() { ... }
    public void Close() { ... }
    public void CleanUp() { ... }
}
tvanfosson
A: 

I would read a few articles by Martin Fowler: Dealing with Roles and Accountability, and then decide.

Stephan Eggermont