Esta pergunta diz respeito ao uso do padrão Decorator para adicionar pouca funcionalidade a objetos de classes grandes.
Seguindo o padrão clássico do Decorator, considere a seguinte estrutura de classes:

Por exemplo, imagine que isso acontece dentro de um jogo. As instâncias de ConcreteCharacterDecoratordestinam-se a adicionar pouca funcionalidade ao ConcreteCharacter'empacotamento'.
Por exemplo, methodA()retorna um intvalor que representa o dano que o personagem causa aos inimigos. O ConcreteCharacterDecoratorsimplesmente adiciona a esse valor. Portanto, ele só precisa adicionar código methodA(). A funcionalidade de methodB()permanece a mesma.
ConcreteCharacterDecorator ficará assim:
class ConcreteCharacterDecorator extends AbstractCharacterDecorator{
ConcreteCharacter character;
public ConcreteCharacterDecorator(ConcreteCharacter character){
this.character = character;
}
public int methodA(){
return 10 + character.methodA();
}
public int methodB(){
character.methodB(); // simply delegate to the wrapped object.
}
}
Isso não é problema com pequenas classes contendo dois métodos.
Mas e se AbstractCharacterdefinidos 15 métodos? ConcreteCharacterDecoratorteria que implementar todos eles, mesmo que apenas para adicionar pouca funcionalidade.
Terminarei com uma classe que contém um método que adiciona um pouco de funcionalidade e outros 14 métodos que simplesmente delegam ao objeto interno.
Seria assim:
class ConcreteCharacterDecorator extends AbstractCharacterDecorator{
ConcreteCharacter character;
public ConcreteCharacterDecorator(ConcreteCharacter character){
this.character = character;
}
public int methodA(){
return 10 + character.methodA();
}
public int methodB(){
character.methodB(); // simply delegate to the wrapped object.
}
public int methodC(){
character.methodC(); // simply delegate to the wrapped object.
}
public int methodD(){
character.methodD(); // simply delegate to the wrapped object.
}
public int methodE(){
character.methodE(); // simply delegate to the wrapped object.
}
public int methodF(){
character.methodF(); // simply delegate to the wrapped object.
}
public int methodG(){
character.methodG(); // simply delegate to the wrapped object.
}
public int methodH(){
character.methodH(); // simply delegate to the wrapped object.
}
public int methodI(){
character.methodI(); // simply delegate to the wrapped object.
}
public int methodJ(){
character.methodJ(); // simply delegate to the wrapped object.
}
public int methodK(){
character.methodK(); // simply delegate to the wrapped object.
}
public int methodL(){
character.methodL(); // simply delegate to the wrapped object.
}
public int methodM(){
character.methodM(); // simply delegate to the wrapped object.
}
public int methodN(){
character.methodN(); // simply delegate to the wrapped object.
}
public int methodO(){
character.methodO(); // simply delegate to the wrapped object.
}
}
Obviamente, muito feio.
Provavelmente não sou o primeiro a encontrar esse problema com o Decorator. Como posso evitar isso?
AbstractCharacterDelegator'regular' (já que todos os métodos 'regulares' em Java são virtuais por padrão - o que significa que eles podem ser substituídos por subclasses herdadas)? E sua implementação simplesmente delega para o objeto interno - e se eu quiser mudar isso, simplesmente substitua-o?