Decorator Pattern — StarbucksCoffee

SCENE: 

Starbucks has variable of coffee, in addition of coffee,
you can also ask for several condiments like milk, mocha 
etc.,and have it all topped off with whipped milk. 
Starbucks charges a bit of each of these, today we need 
to built into their order system.

 

The Decorator Pattern:

The Decorator Pattern attaches additional responsibilities to an object

dynamically. Decorators provide a flexible alternative to subclassing

for extending functionality.

 

The Open-Closed Principle:

Classes should be open for extension, but closed for modification.

 

The power of composition on maintaining your code:

1.When you inherit behavior by subclassing, that behavior is set statically

at compile time. In addition, all subclasses must inherit the same

behavior. If however, you can extend an object’s behavior through

composition, then you can do this dynamically at runtime.

2.It is possible to add multiple new responsibilities to objects through this

technique, including responsibilities that were not even thought of by the

designer of the superclass. And, you don’t have to touch their code!

3.By dynamically composing objects, you can add new functionality by

writing new code rather than altering existing code. Because you’re not

changing existing code, the chances of introducing bugs or causing

unintended side effects in pre-existing code are much reduced.

 

Talk is cheap, let’s pulse-on.

The Class diagram:

Code:

1. abstract the Beverage class:

public abstract class Beverage {

    public String getDescription() {
        return "";
    }

    public abstract double cost();
}

2. abstract the Decorater class by extends Beverage class:

public abstract class Decorater extends Beverage {
    public abstract String getDescription();
}

3. add all kinds of coffee you like:

public class Cappuccino extends Beverage {

    public String getDescription() {
        return "Cappuccino";
    }

    @Override
    public double cost() {
        return 1.22;
    }
}
public class Luckyin extends Beverage {

    public String getDescription() {
        return "Luckyin";
    }

    @Override
    public double cost() {
        return 1.09;
    }
}

4. add all kinds of Decorater you like:

public class Mocha extends Decorater {

    Beverage beverage;

    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + " + Mocha";
    }

    @Override
    public double cost() {
        return .3 + beverage.cost();
    }
}
public class Milk extends Decorater {

    Beverage beverage;

    public Milk(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + " + Milk";
    }

    @Override
    public double cost() {
        return 0.4 + beverage.cost();
    }
}

5. have a test:

public class StarbucksCoffee {

    public static void main(String[] args) {
        Beverage cappuccino =  new Cappuccino();
        Beverage luckyin = new Luckyin();
        System.out.println(cappuccino.getDescription() + " cost: " + cappuccino.cost());
        System.out.println(luckyin.getDescription() + " cost: " + luckyin.cost());
        Milk cappuccinoWithMilk = new Milk(cappuccino);
        Mocha luckyinWithMocha = new Mocha(luckyin);
        System.out.println(cappuccinoWithMilk.getDescription() + " cost: " + cappuccinoWithMilk.cost());
        System.out.println(luckyinWithMocha.getDescription() + " cost: " + luckyinWithMocha.cost());
    }
}

6.output:

Cappuccino cost: 1.22
Luckyin cost: 1.09
Cappuccino + Milk cost: 1.62
Luckyin + Mocha cost: 1.3900000000000001

finished!!!

Real World Decorators: Java I/O

BufferedInputStream bis =

new BufferedInputStream (new FileInputStream(new File (“hello.txt”)));

Leave a Reply

Your email address will not be published. Required fields are marked *