1

I'm fairly new at using design patterns and I am currently making a small game for my uni course that I have to use the decorator pattern for creating the different classes of NPC however I think that I have misunderstood how the decorator pattern works.

At the moment all what changes between the classes of NPC's are the attack value, health and speed stats. What I am really unsure of is if there is a way of passing these values into the decorated object from the decorator or do i have the wrong impression of the decorator pattern.

  • 3
    You have to use the decorator pattern? Because it totally does not apply here. – DeadMG Jan 3 '15 at 21:30
  • @DeadMG see that's what i was thinking, just I'm told that I have to. I'm thinking the reason for this is to make the code extendable to new features but what the real problem is what the best way to set up the health and attack stats – Fraser S Jan 3 '15 at 21:40
4

Think of decorator as wrapping up an object with more functionality. Now this new object has an object inside of it, and the outer object gives it more functionality.

Here's a little pseudo representation of it.

class Watch implements Clock
{
    private Clock clockToBeDecorated;

    public Watch(Clock clock)
    {
        clockToBeDecorated = clock;
    }

    public void StrappToWrist()
    {
        //strap the watch to your wrist
    }

    public DateTime GetTime()
    {
        return clock.GetTime();
    }
}

interface Clock
{
    DateTime GetTime();
}

So now we have all the functionality of a Clock but we can also strap it to our wrist (like you'd expect with a wrist). This is good when you wish to dynamically pass the object into another, so we may wish to put that click into a Watch or a PocketWatch etc.

Wikipedia has a good example using Scrolling Windows in Java as well which may help.

  • Also, Watch : Clock, I thought. – DeadMG Jan 3 '15 at 21:29
  • Thanks that has helped a lot. I think it is the way i had pictured it. Much clearer now. – Fraser S Jan 4 '15 at 0:03
  • The question is marked as C++ but this answer is a C# example. – Klaim Jan 5 '15 at 0:44
  • @Klaim It's just a pseudo language really, I didn't aim for anything in particular. It's probably based a little more on C# due to the use of the word interface, this is just to make it clear that this is intended to be used as an interface rather than a concrete. – Elliot Blackburn Jan 5 '15 at 9:24
1

Decorators have many uses but it doesn't mean that decorator is the appropriate pattern to use for every situation. Given the same requirements, a programmer can always try implementing the same requirements in different patterns to see which one fits best.

In OP's example, I think there is one situation in which the attack, health, speed system can be augmented with a decorator pattern.

For OP's benefit, please read the Coffee Condiment decorator pattern example in Head First Design Patterns.

The situation where I would envision it to be useful is:

  • There is already an underlying NPC class, which provides basic mechanisms for getAttack(), getHealth() and getSpeed().
  • There are a number of gadgets which could be acquired by an NPC object, and these gadgets would temporarily modify the acquirer's properties.

Sample code
(Disclaimer: sample code in C#, not C++)

// Just the statistics. We are not claiming that "CaffeinePack" is a character.
interface CharacterStat
{
    int getAttack();
    int getHealth();
    int getSpeed();
}

interface Character : CharacterStat, CharacterPlanner, ...
{
    // a bunch of other stuff
}

class NPC : Character
{
    public int getAttack() { ... concrete implementation ... }
    public int getHealth() { ... concrete implementation ... }
    public int getSpeed() { ... concrete implementation ... }
}

class CaffeinePack : CharacterStat
{
    private CharacterStat realObject;
    public CaffeinePack(CharacterStat realObject) { this.realObject = realObject; }
    public int getAttack() 
    { 
        return realObject.getAttack(); 
    }
    public int getHealth() 
    { 
        return (int)(realObject.getHealth() * 0.8); 
    }
    public int getSpeed() 
    { 
        return (int)(realObject.getSpeed() * 1.2);
    }
}
  • thanks unfortunately i need to use a decorator pattern however I will defiantly keep this in mind for future reference. – Fraser S Jan 4 '15 at 0:05
  • Wouldn't needing to replace references to the original object be a problem here? – StarWeaver Jan 4 '15 at 12:21
  • @StarWeaver Yes, so my code isn't a 100% example of decorator. In fact, that incoherence (a decorator must implement the full contract of the object it is wrapping) was pointed out in the discussion link I mentioned above, and in that link others have provided alternatives to decorator pattern as well. Contrast this to Java and C#'s stream classes - there, decorator classes do implement the full contract of the abstract stream; there is no cognitive dissonance in that use case. – rwong Jan 4 '15 at 19:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.