Decorator Design Pattern Applied
Hi there!
Today i’m gonna show the decorator design pattern in action. The decorator design pattern is a largelly used design pattern while dealing with grafics, trees and dynamic changes during runtime.
It is also a greate choice if you are looking or trying to do recursion with. I love it. In this post we will implement a students decoration. We will decorate it with degrees and doctor titles. A nice example to see how it works in the real world.
First of all, let’s take a look at the UML diagram of it in its simpliest variety. After that we will take the analogy for our example.
The simpliest UML
Pay close attention, because once you understand that, everything will become clear and simple to understand. That’s the reason I’m putting the simplest model here first.
Understanding the Details
The decorable will be every concrete implementation of the common interace Decorable. The decorators will be every implementation of the abstract class Decorator. Which defines the decorator’s contract holding an instance to decorables. Let’s dive into some code to fix it:
// 1. COMMON INTERFACE FOR DECORABLES public interface Decorable { public String getDescription(); } // 2. THE ABSTRACT DECORADOR WHICH HOLDS A REFERENCE TO DECORABLES public abstract class Decorator implements Decorable { protected Decorable component; public Decorator(Decorable component){ super(); this.component=component; } }
The Analogy to our Students example
Let’s start again with the UML diagram first:
The common decorable Girl
Here we start with the analogies. The interface Girl is the decorable. GirlDecorator defines the abstract decorator’s contract with the concrete decorators bellow.
// 1. COMMON INTERFACE FOR DECORABLES public interface Girl { public String getDescription(); } // 2. THE ABSTRACT DECORADOR WHICH HOLDS A REFERENCE TO DECORABLES public abstract class GirlDecorator implements Girl { protected Girl girl; public GirlDecorator(Girl girl){ super(); this.girl=girl; } } // 3. DEFINING CONCRETE DECORATORS public class Science extends GirlDecorator { public Science(Girl girl) {super(girl);} @Override public String getDescription() { // DECORATES WITH A SCIENCE'S DEGREE return girl.getDescription() + "+Like Science"; } public void caltulateStuff() { // ADDS NEW FEATURES (METHOD) TO IT System.out.println("scientific calculation!"); } } public class Art extends GirlDecorator { public Art(Girl girl) {super(girl);} @Override public String getDescription() {return girl.getDescription() + "+Like Art";} public void draw() {System.out.println("draw pictures!");} } public class Doctor extends GirlDecorator { public Doctor(Girl girl) {super(girl);} @Override public String getDescription() {return girl.getDescription() + "+Like Doctor";} public void calculateStuff() {System.out.println("doctor calculation!");} public void doctorTitle() {System.out.println("doctor title");} }
The Decorables
AmericanGirl and EuropeanGirl are the decorable that will be decorated with degrees and doctor tittles at runtime enhancing its curriculum and abilities.
// 4. AN AMERICAN GIRL WILL BE DEFINED AS A DECORABLE public class AmericanGirl implements Girl { private String description=""; // NORMAL AMERICAN GIRL public AmericanGirl(){ super(); description = "+American"; } @Override public String getDescription() {return description;} } public class EuropeanGirl implements Girl { private String description=""; public EuropeanGirl() { super(); description = "+European"; } @Override public String getDescription() {return description;} }
Testing it
Now let’s see in practise how it looks like. How we can decorate and enhance its abilities at runtime:
public class Client { public static void main(String[] args) { // COMMOM GIRL Girl girl; // CREATING NORMAL AMERICAN GIRL girl = new AmericanGirl(); System.out.println(girl.getDescription()); // DECORANTING AMERICANA GIRL WITH SCIENCE'S DEGREE girl = new Science(girl); System.out.println(girl.getDescription()); // DECORANTING AMERICANA GIRL WITH ART'S DEGREE girl = new Art(girl); System.out.println(girl.getDescription()); // EUROPEAN GIRL HAS ALREADY ALL DEGREES Girl europeia = new Science(new Art(new EuropeanGirl())); System.out.println(europeia.getDescription()); // DOCTOR HAS NEW FUNCTIONS girl = new Doctor(girl); System.out.println(girl.getDescription()); // BECAUSE DOCTOR EXTENDS FROM COMMON GIRL, IT CAN DO A DOWNCAST ((Doctor)girl).doctorTitle(); ((Doctor)girl).calculateStuff(); // PAY ATTENTION THAT WE USE THE SAME INSTANCE, BUT THEY BEHAVIOR DIFFERENT // AT DIFFERENT TIME SLOTS. THE CLIENT HAS THE IMPRESSION THAT WE HAVE // CHANGED THE IMPLEMENTATION, BUT IN FACT NOT. } }
That’s all! Hope you like it!
Reference: | Decorator Design Pattern Applied from our JCG partner Ricardo Ferreira at the Clean Code Development – Quality Seal blog. |
Thanks. And might want to have a native English speaker check your work for spelling errors. They can become distracting:
largelly => largely
grafics => graphics
greate => great
interace => interface
and so on.
tittles = titties? Lol