Permite acrescentar responsabilidades a objetos individuais de forma dinâmica e transparente, sem afetar outros objetos.
Em um jogo lutadores de MMA (Mixed Martial Arts) brasileiros e japoneses utilizam diversos estilos de arte marcial (karatê, judô e jui-jitsu). Durante a luta eles podem mudar a arte utilizada nos golpes para ataque e defesa. O jogador atuando como técnico decide como configurar cada lutador de acordo com esses diferentes estilos de arte marcial.
A implementação da abstração Fighter é organizada em duas hierarquias de classes separadas, uma hierarquia básica para variação das nacionalidades dos lutadores (BrazilianFighter, JapaneseFighter) e outra hierarquia de decoradores para variação das artes marciais dos lutadores (Karate, Judo, Jiu-Jitsu). MartialArt (Decorator) é um Fighter e mantém uma referência para outro objeto Fighter (Component) e delega a execução dos golpes para esse objeto. Suas subclasses (Concrete Decorators) redefinem os métodos de golpes herdados acrescentando comportamentos extras antes e/ou depois da delegação, permitindo combinar as duas hierarquias sem ter que criar uma classe para cada possível combinação evitando, assim, uma explosão de classes.
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package com.padroesdr.decorator.exemplos.mma;
public class JiuJitsu extends MartialArtDecorator {
public JiuJitsu(Fighter fighter) {
super(fighter);
}
@Override
public void toAttack() {
component.toAttack();
System.out.println("Attacking like a Jujitsuka!");
}
@Override
public void defend() {
component.defend();
System.out.println("Defeding like a Jujitsuka!");
}
}
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package com.padroesdr.decorator.exemplos.mma;
/**
*
* @author Adriano Gonçalves
*/
public class BrazillianFighter extends FighterImpl {
@Override
public void toAttack() {
System.out.println("Beginning a Brazillian attack!");
}
@Override
public void defend() {
System.out.println("Defending a Brazillian defence!");
}
}
package com.padroesdr.decorator.exemplos.mma;
public class Principal {
public static void main(String args[]) {
System.out.println("Fighter 1:");
Fighter fighter1 = new JapaneseFighter();
fighter1 = new Karate(fighter1);
fighter1.toAttack();
fighter1.defend();
// Changing the martial art in runtime
System.out.println("Changing the Japanese martial art in runtime...");
/* The following lines aim to "undecorate" the last martial art, due to the only one martial art at time request
* from this problem.
* This approach is only for making this example simpler, for learning purposes. A desirable approach would be
* creating all the instances through the Factory pattern, and controlling the decorations and undecorations
* inside a manager class.
*/
if (fighter1 instanceof MartialArtDecorator) {
fighter1 = ((MartialArtDecorator) fighter1).getComponent();
}
fighter1 = new Judo(fighter1);
fighter1.toAttack();
fighter1.defend();
System.out.println("Fighter 2:");
Fighter fighter2 = new BrazillianFighter();
fighter2 = new JiuJitsu(fighter2);
fighter2.toAttack();
fighter2.defend();
}
}
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package com.padroesdr.decorator.exemplos.mma;
public abstract class FighterImpl implements Fighter {
@Override
public abstract void toAttack();
@Override
public abstract void defend();
}
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Interface.java to edit this template
*/
package com.padroesdr.decorator.exemplos.mma;
public interface Fighter {
public void toAttack();
public void defend();
}
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package com.padroesdr.decorator.exemplos.mma;
public abstract class MartialArtDecorator implements Fighter {
protected Fighter component;
public MartialArtDecorator(Fighter component) {
this.component = component;
}
@Override
public abstract void toAttack();
@Override
public abstract void defend();
// Houston, we've got a problem!
public Fighter getComponent() {
return this.component;
}
}
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package com.padroesdr.decorator.exemplos.mma;
public class MartialArtManager {
private static MartialArtManager instance;
public MartialArtManager getSoleInstance() {
if (instance == null) {
instance = new MartialArtManager();
}
return instance;
}
public static void setMartialArt(Fighter fighter) {
}
}
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package com.padroesdr.decorator.exemplos.mma;
public class Karate extends MartialArtDecorator {
public Karate(Fighter fighter) {
super(fighter);
}
@Override
public void toAttack() {
component.toAttack();
System.out.println("Attacking like a Karateka!");
}
@Override
public void defend() {
component.defend();
System.out.println("Defeding like a Karateka!");
}
}
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package com.padroesdr.decorator.exemplos.mma;
/**
*
* @author Adriano Gonçalves
*/
public class JapaneseFighter extends FighterImpl {
@Override
public void toAttack() {
System.out.println("Beginning a Japanese attack!");
}
@Override
public void defend() {
System.out.println("Defending a Japanese defence!");
}
}
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package com.padroesdr.decorator.exemplos.mma;
public class Judo extends MartialArtDecorator {
public Judo(Fighter fighter) {
super(fighter);
}
@Override
public void toAttack() {
component.toAttack();
System.out.println("Attacking like a Judoka!");
}
@Override
public void defend() {
component.defend();
System.out.println("Defeding like a Judoka!");
}
}