Template Method: Génios da Lâmpada (exemplo)

From Wiki**3

As classes abaixo são parte da implementação de um domínio onde génios saem de lâmpadas mágicas e concedem desejos. Os génios não são todos iguais e alguns nem parecem génios...

A secção "Domínio" apresenta uma especificação informal do domínio, estabelecendo algumas restrições à programação das classes envolvidas.

O Domínio

Uma lâmpada mágica (classe MagicLamp) liberta génios quando esfregada (método rub). Os génios podem ser bem ou mal-humorados. O humor dos génios é determinado pelas condições da lâmpada: sempre que a lâmpada tiver sido esfregada um número par de vezes (sem contar a actual), o génio sai mal-humorado. A quantidade de génios disponíveis é determinada no momento de encantamento da lâmpada (criação). Depois de esgotados os génios disponíveis, já não adianta esfregar a lâmpada para obter um génio, bem ou mal-humorado: nestas condições, a lâmpada cria um pequeno demónio que responde a pedidos de forma literal mas perversa. Devido a requisitos de sustentabilidade ambiental, as normas de produção exigem que as lâmpadas sejam recarregáveis. Assim, é possível voltar a obter génios quando se esfrega a lâmpada (em número igual ao inicial). O processo de recarregamento exige apenas que um demónio seja alimentado à lâmpada (método feedDemon).

Quando se cria uma nova lâmpada é necessário indicar a quantidade inicial de génios que é possível invocar. É possível saber quantos génios ainda estão disponíveis na lâmpada (método getGenies). É ainda possível saber quantas vezes a lâmpada já foi recarregada (método getDemons). Quando se esfrega a lâmpada, deve-se indicar quantos desejos se espera que o génio realize (independentemente de o génio os poder negar).

A classe MagicLamp deve saber comparar as suas instâncias (através do método equals). Considera-se que duas lâmpadas são iguais se tiverem a mesma capacidade e se os valores retornados pelos métodos getGenies e getDemons forem iguais.

Nota: a lâmpada liberta apenas um génio de cada vez.

Génios

Um génio bem-humorado (classe FriendlyGenie) concede todos os desejos que lhe forem colocados (método grantWish e retorno true), até ao limite com que foi chamado da lâmpada. Depois do limite já não são concedidos desejos (retorno false). É possível saber quantos desejos já foram concedidos (método getGrantedWishes) e quantos ainda existem disponíveis (método getRemainingWishes).

Nota: o génio concede apenas um desejo de cada vez.

Um génio mal-humorado (classe GrumpyGenie) concede apenas o primeiro desejo que lhe for colocado (método grantWish e retorno true), independentemente do limite com que foi chamado da lâmpada (retorno false após o primeiro). É possível saber se o desejo já foi realizado (método getGrantedWishes retorna 1).

Um demónio (classe RecyclableDemon) concede todos os desejos que lhe forem colocados (método grantWish e retorno true), independentemente do limite com que foi chamado da lâmpada. Se o demónio for recolocado na lâmpada (para a recarregar), já não pode realizar mais desejos (retorno false). É possível saber quantos desejos já foram concedidos (método getGrantedWishes).

Nota: o demónio concede apenas um desejo de cada vez.

Strings

O método toString, aplicado aos génios e ao demónio, deve devolver uma das cadeias de caracteres abaixo. Os símbolos # representam contadores apropriados a cada caso.

  • Friendly genie has granted # wishes and still has # to grant.
  • Grumpy genie has granted a wish. / Grumpy genie has a wish to grant. (consoante já concedeu ou não o pedido)
  • Recyclable demon has granted # wishes. / Demon has been recycled. (antes e depois de recarregar uma lâmpada)

Definição dos Génios

A solution to this problem has already been seen in Arabian Nights in Java.