简体   繁体   中英

Decorator pattern limitations

I have a usecase where I am trying to use decorator pattern but not sure if it is the right way of using pattern. I have 2 message publisher class. First publisher takes json as input and publish message Second publisher takes bytes as input and publish message

Currently these 2 are separate classes

public class A {
    publish(Json input);
}

public class B {
    publish(byte[] input);
}

I want to decorate B with A instead of creating a separate class. Basically user would give input as Json and it would be converted to compressed bytes and published to a sink. But problem what i can think here is, while I can decorate B with A, I can't decorate A with B, reason being json can be converted to byte stream but all byte stream can't be converted to json format, and doing so would throw exception.

All decorator classes inherit same parent interface, so one can dcorate classes in any possible combination. So for decorator pattern to work properly, all of decorators must be compatible with each others irrespective of orders in which they are applied. Is this understanding correct or am I missing something in decorator pattern.

All decorator classes inherit same parent interface, so one can decorate classes in any possible combination. So for decorator pattern to work properly, all of decorators must be compatible with each others irrespective of orders in which they are applied. Is this understanding correct?

yeah, you are absolutely right. This is how polymorphism works.

For instance, we want to calculate overall sum of coffee with whip. Usually, price has the same type everywhere. If you have different types, then you need to create some converter class.

Let me show an example via C#.

This is an abstraction of beverages:

public abstract class Beverage
{
    public abstract string GetDescription();

    public abstract double GetCost();
}

and Espresso is concrete implementation of beverage:

public class Espresso: Beverage { public override double GetCost() { return 1; }

public override string GetDescription()
{
    return "Espresso";
}

}

This is an abstraction of some addings that can be added or decorated into beverages:

public abstract class BeverageDecorator : Beverage
{
    protected Beverage _beverage;
}

and WhipDecorator is concrete implementation of beverage decorator adding:

public class WhipDecorator: BeverageDecorator
{
    public WhipDecorator(Beverage beverage)
    {
        _beverage= beverage;
    }

    public override double GetCost()
    {
        return _beverage.GetCost() + 1;
    }

    public override string GetDescription()
    {
        return _beverage.GetDescription() + " Whip";
    }
}

The above code can be run like this:

Beverage espresso = new Espresso();
espresso = new WhipDecorator(espresso);

double cost = espresso.GetCost(); // OUTPUT: 2
string description = espresso.GetDescription(); // OUTPUT: "Espresso Whip"

I highly recommend you to read this fascinating book Head First Design Patterns, 2nd Edition

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM