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 ConcreteCharacterDecorator
destinam-se a adicionar pouca funcionalidade ao ConcreteCharacter
'empacotamento'.
Por exemplo, methodA()
retorna um int
valor que representa o dano que o personagem causa aos inimigos. O ConcreteCharacterDecorator
simplesmente 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 AbstractCharacter
definidos 15 métodos? ConcreteCharacterDecorator
teria 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?