Home > Java > javaTutorial > Decorator Pattern

Decorator Pattern

Mary-Kate Olsen
Release: 2024-11-05 03:40:02
Original
230 people have browsed it

What is Decorator Pattern?

Decorator pattern is a structural design pattern that attaches additional behaviors to an object dynamically. Decorators provide a flexible extension reason by composition rather than subclassing (inheritance).

When to use it?

Use Decorator pattern when you want to construct an object by adding small behaviors at runtime.

UML diagram

Decorator Pattern

Decorator class uses composition and inheritance, it's crucial to understand their intent.
In Decorator pattern, we use the same type for both components & decorators. Decorator composites Component object to get behavior, that is, obtaining fields or methods defined in Component object. While Decorator inherits (extends) Component so that Decorator object can be declared as Component object.

Decorator pattern achieves open-closed principle, namely, open for extension and closed for modification. It's easy to add components or decorators. for instance, if you want to add another concrete decorator, you just need to create a class representing it and extends Decorator class.

Example

Imagine we're developing a system for an ice cream shop. The shop has various ice creams and toppings. The system needs to display an ice cream description (including its toppings) and cost.

Decorator Pattern

  • Components (ice creams) and Decorators (toppings) have common interface IceCream class, they both declare as IceCream object.
  • Each concrete ice cream overrides cost method since prices are different for each.
  • Topping class provides interface for concrete toppings and holds reference to an IceCream.
  • If system needs another topping, say caramel source, what you need to do is just creating CaramelSource class which extends Topping class.

Implementation in Java

IceCream class:

// Component class
public abstract class IceCream {

    public String description = "Unknown ice cream";

    public String getDescription() {
        return description;
    }

    public abstract double cost();
}
Copy after login

ChocolateIceCream class:

// Concrete component class
public class ChocolateIceCream extends IceCream {

    public ChocolateIceCream() {
        description = "ChocolateIceCream";
    }

    @Override
    public double cost() {
        return 1.99;
    }
}
Copy after login

Topping class:

// Base decorator class
public abstract class Topping extends IceCream {

    public IceCream iceCream;

    // All subclasses (concrete decorator classes) need to implement getDescription method,
    // by declaring this method as abstract, we enforce all subclasses to implement this method
    public abstract String getDescription();
}
Copy after login

MapleNuts class:

// Concrete decorator class
public class MapleNuts extends Topping {

    public MapleNuts(IceCream iceCream) {
        this.iceCream = iceCream;
    }

    @Override
    public String getDescription() {
        return iceCream.getDescription() + ", MapleNuts";
    }

    @Override
    public double cost() {
        return iceCream.cost() + .30;
    }
}
Copy after login

PeanutButterShell class:

// Concrete decorator class
public class PeanutButterShell extends Topping {

    public PeanutButterShell(IceCream iceCream) {
        this.iceCream = iceCream;
    }

    @Override
    public String getDescription() {
        return iceCream.getDescription() + ", PeanutButterShell";
    }

    @Override
    public double cost() {
        return iceCream.cost() + .30;
    }
}
Copy after login

Client class:

public class Client {

    public static void main(String[] args) {
        IceCream iceCream = new ChocolateIceCream();
        System.out.println(iceCream.getDescription() + ", $" + iceCream.cost());

        iceCream = new MapleNuts(iceCream);
        System.out.println(iceCream.getDescription() + ", $" + iceCream.cost());

        iceCream = new PeanutButterShell(iceCream);
        System.out.println(iceCream.getDescription() + ", $" + iceCream.cost());
    }
}
Copy after login

Output:

ChocolateIceCream, .99
ChocolateIceCream, MapleNuts, .29
ChocolateIceCream, MapleNuts, PeanutButterShell, .59
Copy after login

You can check all the design pattern implementations here.
GitHub Repository


P.S.
I'm new to write tech blog, if you have advice to improve my writing, or have any confusing point, please leave a comment!
Thank you for reading :)

The above is the detailed content of Decorator Pattern. For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template