Mastering Java Design Patterns - Day 9: Decorator Pattern

Mastering Java Design Patterns - Day 9: Decorator Pattern

Hello, everyone! Today, we continue our exploration of Structural Design Patterns with the Decorator Pattern. Yesterday, we covered the Composite Pattern. Now, let’s see how the Decorator Pattern can help us extend the functionality of objects dynamically and flexibly.

What is the Decorator Pattern?

The Decorator Pattern allows you to add behavior to objects dynamically by placing them inside wrapper objects that provide the additional functionality. This pattern is particularly useful when you want to add responsibilities to individual objects without affecting other objects of the same class.

Why Use the Decorator Pattern?

  • Flexibility: It allows you to add or remove functionalities without altering the existing code.
  • Scalability: It enables the combination of multiple behaviours by stacking decorators.
  • Single Responsibility Principle: It promotes cleaner code by adhering to the single responsibility principle, where each class has one reason to change.

How to Implement the Decorator Pattern in Java

Here's a simple implementation of the Decorator Pattern:

// Component interface

interface Coffee {

    String getDescription();

    double getCost();

}        
// Concrete Component

class SimpleCoffee implements Coffee {

    public String getDescription() {
        return "Simple coffee";
    }

    public double getCost() {
        return 2.0;
    }

}        
// Decorator

abstract class CoffeeDecorator implements Coffee {

    protected Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }

    public String getDescription() {
        return decoratedCoffee.getDescription();
    }

    public double getCost() {
        return decoratedCoffee.getCost();
    }

}        
// Concrete Decorators

class MilkDecorator extends CoffeeDecorator {

    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    public String getDescription() {
        return decoratedCoffee.getDescription() + ", milk";
    }

    public double getCost() {
        return decoratedCoffee.getCost() + 0.5;
    }
}

class SugarDecorator extends CoffeeDecorator {

    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }

    public String getDescription() {
        return decoratedCoffee.getDescription() + ", sugar";
    }

    public double getCost() {
        return decoratedCoffee.getCost() + 0.2;
    }

}        
// Client code

public class DecoratorPatternDemo {

    public static void main(String[] args) {

        Coffee coffee = new SimpleCoffee();

        System.out.println(coffee.getDescription() + " $" + coffee.getCost());

        coffee = new MilkDecorator(coffee);

        System.out.println(coffee.getDescription() + " $" + coffee.getCost());

        coffee = new SugarDecorator(coffee);

        System.out.println(coffee.getDescription() + " $" + coffee.getCost());
    }

}        

Discussion:

Have you used the Decorator Pattern to add functionalities to your objects? What scenarios have you found it most beneficial? Share your experiences and examples in the comments below!

?? Call to Action: If you found this post helpful, please like, share, and comment! Follow #ehadjistratis for more insights into Java Design Patterns and other tech topics. Let's continue building a community of learners and practitioners!

Looking forward to your thoughts and experiences!

Stay tuned for tomorrow's topic: Facade Pattern.

#Java #DesignPatterns #DecoratorPattern #Programming #Coding #SoftwareDevelopment #LearningJourney #JuniorDevelopers #TechCommunity #ehadjistratis

要查看或添加评论,请登录

Emmanuel Hadjistratis (he/him)的更多文章

社区洞察

其他会员也浏览了