Padrµes de Projeto Aula 3 – Padr£o Strategy. PADRƒO STRATEGY Padrµes de Projeto - Strategy 2

  • View
    216

  • Download
    0

Embed Size (px)

Text of Padrµes de Projeto Aula 3 – Padr£o Strategy. PADRƒO STRATEGY...

Padres de Projetos

Padres de ProjetoAula 3 Padro Strategy

1Padro StrategyPadres de Projeto - Strategy2Padres de Projeto - Strategy3

Imagine que os donos da Sega lhe contrataram para implementar o jogo do Mortal Kombat III.3ModeloComo vocs implementariam este jogo?Conjunto de lutadoresAtacarDefenderMoverEspecificamenteAtacarsocar(), chutar()Defender j especficoMoverandar(direo), pular(direo)Padres de Projeto - Strategy4O MK3 tem um conjunto de lutadores, onde cada um pode atacar e defender.Mas atacar e defender so conceitos/comportamentos muito gerais. Vamos tornar isto mais especfico.Todos os nossos lutadores podem andar(direo), pular(direo), socar(), chutar() e defender().

Como que vocs fariam isso?

4

ModeloPadres de Projeto - Strategy5

As implementaes de socar(), chutar(), defender(), andar(direcao) e pular(direcao) poderiam ser concretas e ficariam na superclasse.Assim todo novo lutador no precisaria reescrever esses comportamentos. (Herana)

Desenha() deve ser abstrato. Desenhar seria o mtodo responsvel por apresentar/pintar o lutador na tela.Deve ser abstrato porque todos os lutadores so diferentes (em termos de aparncia), logo, cada novo lutador inserido ao projeto deve fornecer uma implementao concreta para o mtodo desenha (especificando suas caractersticas), para que a classe principal possa utilizar o mtodo desenha() de maneira polimrfica. E assim o nosso projeto estaria flexvel para cada novo jogador. Faz sentido n?5Novas funcionalidadesAmbos os lutadores atiram!Como devemos modelar esta nova funcionalidade?Padres de Projeto - Strategy6

E se ns colocssemos o mtodo atirar() na superclasse Lutador? Fica legal?Assim ns conseguiramos reuso do cdigo, e o Nightwolf e o Stryker no precisariam implementar cdigos semelhantes.

Qual o problema disso?Todo Lutador que ns implementssemos poderia atirar, o que no o caso...Liu Kang, por exemplo, poderia atirar.6Novas funcionalidadesInterfaces?Padres de Projeto - Strategy7

O que vocs acham dessa implementao?Parece ser legal n?

Agora ns no quebramos mais a lgica de implementao. Todo novo lutador s ir atirar se implementar a interface Atirador.O que legal da interface Atirador? Agora ns podemos utilizar o mtodo atirar() de modo polimrfico.

Ok. Mas tem um detalhe que no t legal. Esse cdigo no reutilizvel.Tudo bem que o mtodo atirar() de Stryker e NightWolf devem ser diferentes, inclusive porque eles usam diferentes armas.Mas se ns quisermos adicionar ao nosso jogo o personagem ErronBlack... (nas verses que eu joguei ele no existia, mas pesquisei no google e ele aparentemente um caubi do velho oeste... Uiiii que meda.. Kkkkkk)

Enfim, vocs percebem que ns basicamente reescreveramos o mesmo cdigo para Stryker e ErronBlack?E se ns quisssemos criar um outro personagem que possui como um dos comportamentos de ataque a habilidade de atirar com uma arma de fogo convencional, assim como Stryker e Erron Black?Basicamente copiaramos e colaramos o mesmo cdigo nesses personagens. ISTO NO LEGAL!!Se futuramente quisermos mudar algum detalhe no modo como os personagens deveriam atirar com arma de fogo, basicamente deveramos fazer a alterao em todos os personagens.7Novas FuncionalidadesLanar magia!Sub Zero (lana gelo)Rayden (lana raio)Shang Tsung (lana bola de fogo)Jax (lana bola de fogo)Liu Kang (lana bola de fogo)Padres de Projeto - Strategy8Pra ficar mais claro como isso poderia ser uma bola de neve.

Agora ns queremos adicionar ao nosso modelo alguns lutadores que Lanam Magia, ou seja, so bruxos. fato que em Mortal Kombat ns temos vrios lutadores que lanam magia, estes (no slide) so alguns deles, provavelmente deve haver mais.Com o pensamento anlogo ao que tivemos anteriormente, faz sentido que ns criemos uma interface Bruxo, na qual todos os lutadores que lanam magia deveriam implementar. Assim ns conseguiramos utilizar o mtodo lancaMagia() de maneira polimrfica.8

Padres de Projeto - Strategy9

Mas aqui ns temos o mesmo problema que tivemos em Atirador. A interface nos d o poder do polimorfismo, mas no nos d o poder do reuso de cdigo.Nesse caso, ainda mais grave. Temos um comportamento que se repete em 3 lutadores: tanto Jax, como ShangTsung como LiuKang lanam bola de fogo. Isto quer dizer que ns teremos mtodos basicamente iguais, ou pelo menos, bem semelhantes.Algum discorda??? (se sim me mande email pra conversarmos...)

Mais uma vez, temos o problema da mudana de cdigo. Se por algum acaso, precisarmos mudar a forma como o lancaMagia implementado para lancar uma bola de fogo, teremos que ir nas 3 classes e fazer a alterao de forma local. Isso pode ficar ainda pior a medida em que adicionarmos novos lutadores (numa futura implementao de mortal kombat X).

9Qual a nica coisa com a qual podemos contar sempre no desenvolvimento de software?ALTERAOPadres de Projeto - Strategy10

Temos que nos proteger contra essa caracterstica natural no desenvolvimento de software.

Como podemos fazer isso?

Sistemas bem projetados so mais protegidos contra alterao. Quando necessrias, essas alteraes so de menor porte possvel.

10Separando o que muda do que fica igualQuais comportamentos so imutveis?socar(), chutar(), defender();Quais comportamentos so mutveis?atirar(), lancarMagia();O que devemos fazer?Separar o que muda do que fica igual!Como?Que tal criar um conjunto de classes (completamente separadas de Lutador) para cada comportamento?Cada conjunto de classes ir conter todas as implementaes possveis para seu comportamento.Ex.: teramos uma classe para atirar com arma de fogo, outra classe para atirar flechas, etc.Padres de Projeto - Strategy11E agora, o que fazemos? Alm do problema com atirar() e lancarMagia(), a classe Lutador parece estar ok. Dizemos isso porque tudo que est em Lutador no varia. Todos eles socam, chutam e se defendem igualmente.11Separando o que muda do que fica igualPadres de Projeto - Strategy12

12Desenvolvendo os comportamentos de LutadorComo vamos desenvolver o conjunto de classes que implementam os comportamentos de atirar e lanar magia?Padres de Projeto - Strategy13

13

Desenvolvendo os comportamentos de LutadorUtilizaremos interfaces!Padres de Projeto - Strategy14

Agora ns utilizamos uma interface para representar cada comportamento, e cada implementao de comportamento ir implementar uma dessas interfaces.Agora, ao invs de cada Lutador implementar uma dessas interfaces, ns teremos comportamento especficos implementando-as. Ex.: ao invs de Nightwolf implementar a interface Atirador, ns teremos a classe AtirarComArcoEFlecha que implementa a classe Atirador.A ideia que todo lutador tenha uma referncia Atirador.Assim, todo lutador poderia, em tese, atirar.Se um novo lutador surgir com um novo comportamento de Atirador, esse comportamento deve ser implementado, e a classe Lutador simplesmente no precisa ser alterada. A varivel de Atirador pode referenciar este novo comportamento.

E se um lutador no for atirador. Da ele teria uma referncia a um comportamento que no atira (NaoAtirar).

Por composio podemos criar novos Lutadores sem precisar alterar a classe Lutador, e a classe MortalKombat.Alteraes mnimas seriam necessrias se novos tipos de comportamento existissem. Como vamos mostrar adiante.14Padres de Projeto - Strategy15Pela 903284 vez:PROGRAME para uma SUPERCLASSE!

S assim conseguimos utilizar o polimorfismo com eficincia!15

Integrando o comportamento de LutadorPadres de Projeto - Strategy16abstract class Lutador{protected ComportamentoAtirador comportamentoAtirador;protected ComportamentoBruxo comportamentoBruxo;//...public void atirar(){comportamentoAtirador.atirar();}public void lancarMagia(){comportamentoBruxo.lancarMagia();}}

As variveis de comportamento so declaradas com o tipo da interface (superclasse).Assim conseguimos atribuir qualquer subclasse quela varivel, i.e., qualquer comportamento pode ser atribudo.Ex.: comportamentoAtirador pode receber um objeto do tipo AtirarComArmaDeFogo, AtirarComArcoEFlecha, NaoAtirar.Isso pode ser feito em tempo de execucao, e quando novos comportamentos de atirar aparecerem, ns no precisamos mudar Lutador, nem a classe ringue.

Em vez de lidar com o comportamento de atirar em si, o objeto Lutador delega esse comportamento ao objeto relacionado por ComportamentoAtirador.16Padres de Projeto - Strategy17

Esses #, que significam protected, poderiam ser configurados como private.Dem uma olhadinha em Strategy.rar. 17TEM-UM pode ser melhor do que -UMPra que serve a herana?Resp.: um de seus objetivos o reuso de cdigo.Existe outra maneira de reutilizar cdigo seno atravs da herana?Resp.: Sim, atravs de composio!Ao invs de herdar seus comportamentos, os lutadores obtm seu comportamento ao serem compostos com o objeto de comportamento certo.Sistemas que utilizam composio possuem muito mais flexibilidade do que os que usam herana.Conseguimos reuso de cdigo de maneira flexvel e com maior poder de manuteno.A composio permite que os Lutadores alterem seu comportamento em tempo de execuo. (lembra do Shang Tsung?)Padres de Projeto - Strategy18Quando puder, sempre use composio ao invs de herana...

Lembre-se disto!

ExerccioConsiderando o design que ns acabamos de modelar, implemente (papel) a classe Lutador e uma das seguintes classes, que -UM Lutador:

Padres de Projeto - Strategy19

19SoluoPadres de Projeto - Strategy20class NightWolf extends Lutador{public NightWolf(){comportamentoAtirador = new AtirarComArcoEFlecha();comportamentoBruxo = new LancarNada();}}Ops...Inicialmente eu achei que NightWolf no lanava magia (de verdade, eu no sabia...)Aparentemente, ele (MK3) possui uma conexo muito forte com o Raiden (MK2), e lana raios em seus oponentes. Vamos considerar isso como uma magia.Como deveramos proceder para consertar NightWolf?Padres de P

View more >