Decorator
Story
Attach additional responsibilities to an object dynamically.
The spoilers that are added to a car are examples of the Decorator. The spoilers do not change the car itself, but adds additional functionality which is to ‘spoil’ unfavorable air movement across a body of a vehicle in motion, usually described as turbulence or drag.
Image
steve lyon from los angeles, ca, usa, 2013 Porsche 911 Carrera S (8233337583), CC BY-SA 2.0
UML
Implementation
Component.java
package com.hundredwordsgof.decorator;
/**
*
* Component, defines interface for new features which will be added dynamicaly
*
*/
public interface Component {
void operation();
}
ConcreteComponent.java
package com.hundredwordsgof.decorator;
/**
*
* ConcreteComponent, define object where new features can be added
*
*/
public class ConcreteComponent implements Component {
public void operation() {
}
}
Decorator.java
package com.hundredwordsgof.decorator;
/**
*
* Decorator, keep reference to Component object
*
*/
abstract class Decorator implements Component {
protected Component component;
public abstract void operation();
public void setComponent(Component component) {
this.component = component;
}
}
ConcreteDecoratorA.java
package com.hundredwordsgof.decorator;
/**
*
* ConcreteDecoratorA, add features to component
*
*/
public class ConcreteDecoratorA extends Decorator {
private boolean state;
public void operation() {
state = true;
this.component.operation();
}
public boolean isState() {
return state;
}
}
ConcreteDecoratorB.java
package com.hundredwordsgof.decorator;
/**
*
* ConcreteDecoratorB, add features to component
*
*/
public class ConcreteDecoratorB extends Decorator {
private boolean behaviorMethodInvoked = false;
public void operation() {
this.component.operation();
addedBehavior();
}
private void addedBehavior() {
behaviorMethodInvoked = true;
}
protected boolean isBehaviorMethodInvoked() {
return behaviorMethodInvoked;
}
}
Usage
DecoratorTest.java
package com.hundredwordsgof.decorator;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
/**
* Test Decorator pattern.
*/
public class DecoratorTest {
@Test
public void testDecorator() {
Component component = new ConcreteComponent();
Decorator decoratorA = new ConcreteDecoratorA();
decoratorA.setComponent(component);
decoratorA.operation();
assertEquals(true, ((ConcreteDecoratorA) decoratorA).isState());
Decorator decoratorB = new ConcreteDecoratorB();
decoratorB.setComponent(component);
assertEquals(false,
((ConcreteDecoratorB) decoratorB).isBehaviorMethodInvoked());
decoratorB.operation();
assertEquals(true,
((ConcreteDecoratorB) decoratorB).isBehaviorMethodInvoked());
}
}