O conceito
Estou programando uma interface sobre o pygame como um projeto pessoal, para facilitar a criação de jogos para mim.
Até agora eu consegui projetar uma arquitetura que se comporta assim:
- Objetos são componentes exibíveis que podem aparecer e se mover na tela
- Objetos podem ter objetos filhos
- Quando um objeto é exibido, ele pede a todos os filhos que se exibam na superfície dos pais.
- Os objetos têm três elementos importantes: um sistema de retorno de chamada, um sistema gráfico e um sistema físico para agir, exibir e mover respectivamente.
Então, quando eu quero criar uma "cena" de jogo, eu crio um objeto "raiz" que contém outros objetos como o jogador, o mouse, o chão, monstros ...
Então eu só tenho que pedir para a raiz se exibir, e todo objeto aparece recursivamente.
Eu projetei isso sem saber sobre o padrão composto no início, apenas o básico da OOP.
Minha principal questão era tornar a propriedade de substitutibilidade de objetos que vem da herança funcionar bem com a composição recursiva que fiz.
Quero dizer que tenho uma classe "abstrata" chamada "Objeto" (coloquei o resumo em aspas porque o Python realmente não tem esse conceito) que é herdada por classes como "Imagem" (para poder exibir) ou "MovingObject" (para poder mover).
Aqui, a herança serve para estender minhas habilidades com objetos.
Mas meu padrão composto exige que "grupos de objetos sejam considerados iguais a objetos únicos".
Então, quando eu chamo recursivamente um método de um objeto, ele chama esse método de cada filho do objeto, independentemente do fato de que alguns deles podem não ter esse método.
Exemplo
Por exemplo, vamos usar esse elemento raiz:
- root (imagem)
- player (MovingObject)
- cloud (MovingObject)
- plano de fundo (imagem)
- sol (imagem)
Agora vamos supor que queremos chamar o método move()
no elemento raiz, para fazer com que cada filho seja movido: Primeiro, não podemos porque root é uma instância de Imagem, portanto, ele não conhece o método move()
. Mas mesmo se fosse o caso, as crianças "background" e "sun" não saberiam disso.
Então eu decidi colocar um método vazio move()
dentro da minha classe de objeto "abstract", então todo objeto sabe disso, mesmo que não faça nada.
A questão é que minha classe Object agora contém métodos vazios que não entende nem precisa, apenas para permitir o comportamento recursivo.
Solução possível
Então eu ouvi sobre toda a confusão de "herança versus composição" e uma das soluções que me veio à mente foi parar de usar a herança para habilidades de objetos e usar a composição. Isso significa que eu criaria, por exemplo, uma classe "Body", uma classe "Image" e uma classe "Callback" que representariam ações diferentes, e então as encaixaria em uma instância de Object para "equipá-lo" e dar mais poder a ele. .
Mas então eu pensei que isso dificilmente mudaria alguma coisa porque eu teria que chamar move()
, e então o objeto verificaria se ele tinha o plug-in do Body e o usaria. Mas ainda requer que o método move()
esteja presente dentro da classe Object.
Perguntas
Então, estou me voltando para vocês para me dar conselhos sobre meu padrão:
- Eu entendi bem como o padrão composto funciona?
- A minha abordagem está correta?
- O uso de aulas de "plug-in" me ajudará?
- O comportamento recursivo é uma boa ideia?
- Existem outros padrões mais adequados às minhas necessidades?
Espero que você possa me dar algumas dicas!