• Nenhum resultado encontrado

De acordo com sua defini¸c˜ao inicial, o padr˜ao Factory Method tem como objetivo: “De- finir uma interface para criar um objeto mas deixar que subclasses definam que classe instanciar. Factory Method permite que uma classe delegue a responsabilidade de instan- ciamento `as subclasses” [Gamma et al., 1994]. Factory Method pode ser confundido com o padr˜ao Abstract Factory, mas sua diferen¸ca est´a no fato de delegar a instancia¸c˜ao dos objetos diretamente para as subclasses.

Este padr˜ao pode ser bem aplicado a situa¸c˜oes e problemas em que uma classe n˜ao pode antecipar que tipo de objetos deve criar, assim como precisa delegar `as subclasses a responsabilidade de especificar os objetos que ser˜ao instanciados. O padr˜ao Factory Method tamb´em permite, dependendo dos objetivos da implementa¸c˜ao, que seja poss´ıvel localizar a subclasse que ir´a ser a respons´avel por instanciar determinado objeto.

Padrão Factory Method 40

Figura 3.5: Execu¸c˜ao do exemplo para o padr˜ao Builder em Java.

3.4.1

Exemplo utilizado para este padr˜ao

No exemplo que foi implementado para este padr˜ao, retirado de [Freeman et al., 2004], houve novamente uma implementa¸c˜ao de uma pizzaria. Neste caso, o cen´ario ´e parecido com o utilizado no padr˜ao Abstract Factory, com a diferen¸ca de que ´e menos complexo, pois n˜ao existem as fam´ılias de ingredientes para cada sabor diferente de pizza, apesar de mesmos sabores de pizzas em franquias diferentes possu´ırem ingredientes diferentes.

A pizzaria possui ainda suas duas franquias de pizza, uma em Nova Iorque, representada pela classe NYPizzaStore e outra em Chicago, representada pela classe ChicagoPizzaStore. A id´eia central ´e a de n˜ao instanciar os objetos representando cada sabor de pizza de diferentes franquias diretamente, e sim utilizar uma classe intermedi´aria que receber´a o tipo de pizza a ser instanciada e criada, assim como a franquia da qual a mesma pertence para que este objeto possa ser criado pelas subclasses referentes ao sabor selecionado.

Figura 3.6: Execu¸c˜ao do exemplo para o padr˜ao Builder em ooErlang.

Portanto, para este exemplo existe uma classe chamada PizzaStore, que possui a in- terface necess´aria para que se possa criar qualquer sabor de pizza desejado, por meio do m´etodo abstrato createPizza(). Este m´etodo ´e implementado em duas outras subclasses, chamadas NYPizzaStore (relacionada com os sabores de pizza de Nova Iorque) e Chicago- PizzaStore (para criar os sabores de Chicago). Portanto, sempre a cria¸c˜ao de cada pizza vai ser solicitada na classe principal, PizzaTestDrive, que, por sua vez, repassa esta res- ponsabilidade de cria¸c˜ao `as subclasses.

Existe tamb´em a classe Pizza, que possui todos os atributos e m´etodos, representando genericamente cada objeto pizza a ser criado. Nesta modelagem ´e poss´ıvel perceber que o c´odigo sujeito a modifica¸c˜oes ´e isolado do c´odigo que n˜ao muda. Os m´etodos da classe Pizza por exemplo, que n˜ao s˜ao pass´ıveis de modifica¸c˜ao, est˜ao separados dos tipos de pizza, que podem modificar-se com o tempo (sabores podem ser inclu´ıdos e retirados com o tempo). A figura 3.7 mostra um diagrama de classes simplificado para melhor entendimento do cen´ario.

Pode-se observar que as classes NYPizzaStore e ChicagoPizzaStore herdam os m´etodos da classe PizzaStore, que no caso, representa a pizzaria como um todo. As subclasses

Padrão Factory Method 42

Figura 3.7: Diagrama de classes do exemplo para o padr˜ao Factory Method. s˜ao as franquias desta pizzaria, cada uma com suas caracter´ısticas diferentes de sabores. Cada subclasse possui o m´etodo createPizza, respons´avel por iniciar a cria¸c˜ao da pizza propriamente dita.

3.4.2

Compara¸c˜ao das implementa¸c˜oes em Java e ooErlang

Tanto em Java quanto em ooErlang, a mesma estrutura foi criada, de acordo com o diagrama de classes simplificado mostrado na figura 3.7. Verificando o fonte da classe PizzaStore, conforme os c´odigos em 3.4.1 e 3.4.2 que mostram as implementa¸c˜oes em Java e ooErlang respectivamente, verifica-se que a cria¸c˜ao da pizza ´e repassada para as subclasses

enquanto que o preparo permanece nesta classe.

1 public abstract class PizzaStore { 2

3 abstract Pizza createPizza(String item); 4

5 public Pizza orderPizza(String type) { 6 Pizza pizza = createPizza(type);

7 System.out.println("--- Making a " + pizza.getName() + " ---"); 8 pizza.prepare(); 9 pizza.bake(); 10 pizza.cut(); 11 pizza.box(); 12 return pizza; 13 } 14 }

C´odigo 3.4.1: Classe PizzaStore em Java

1 -class(pizzaStore). 2 -export([create_pizza/1, order_pizza/2]). 3 4 methods. 5 6 create_pizza(Item) -> null. 7 8 order_pizza(Type, String) ->

9 Object = {String, ObjectID},

10 Pizza = Object::create_pizza(Type), 11

12 io:format("--- Making a ~p --- ~n", [Pizza::get_name()]), 13 Pizza::prepare(),

14 Pizza::bake(), 15 Pizza::cut(), 16 Pizza::box(), 17 Pizza.

C´odigo 3.4.2: Classe PizzaStore em ooErlang

Desta forma o c´odigo que n˜ao ´e sujeito a modifica¸c˜oes, permanece isolado do c´odigo que pode modificar-se com o tempo. A classe Pizza possui as implementa¸c˜oes dos m´etodos que tratam dos procedimentos para finaliza¸c˜ao do processo de constru¸c˜ao da pizza, mas isto ocorre apenas depois da pizza de fato j´a ter recebido seus ingredientes. Os c´odigos 3.4.3 e 3.4.4 mostram a implementa¸c˜ao da classe Pizza em Java e ooErlang, respectivamente.

Existem algumas diferen¸cas pr´oprias entre as sintaxes do Java e ooErlang, por´em a utiliza¸c˜ao dos atributos e dos m´etodos ´e a mesma. As classes NYPizzaStore e Chicago-

Padrão Factory Method 44

1 public abstract class Pizza { 2 String name;

3 String dough; 4 String sauce;

5 ArrayList toppings = new ArrayList(); 6 7 void prepare() { 8 System.out.println("Preparing " + name); 9 System.out.println("Tossing dough..."); 10 System.out.println("Adding sauce..."); 11 System.out.println("Adding toppings: "); 12 for (int i = 0; i < toppings.size(); i++) {

13 System.out.println(" " + toppings.get(i));

14 }

15 } 16

17 void bake() {

18 System.out.println("Bake for 25 minutes at 350"); 19 }

20

21 void cut() {

22 System.out.println("Cutting the pizza into diagonal slices"); 23 }

24

25 void box() {

26 System.out.println("Place pizza in official PizzaStore box"); 27 }

C´odigo 3.4.3: Classe Pizza em Java

PizzaStore s˜ao similares em suas implementa¸c˜oes, com a diferen¸ca de que cada uma trata dos sabores para suas pr´oprias lojas. Cada franquia possui os mesmos sabores sendo que, o que diferencia os sabores de uma loja para a outra s˜ao os ingredientes utilizados para o preparo das pizzas. Os c´odigos 3.4.5 e 3.4.6 mostram as respectivas implementa¸c˜oes em Java e ooErlang da classe NYPizzaStore.

Na execu¸c˜ao deste exemplo ´e utilizada a classe PizzaTestDrive. Nesta classe, s˜ao inici- almente criadas instˆancias das classes NYPizzaStore e ChicagoPizzaStore, para que sejam as respons´aveis por tratar dos pedidos dos clientes de pizza. Em seguida s˜ao instanciadas v´arias pizzas, para v´arios sabores de pizza nas duas franquias da pizzaria. O m´etodo utili- zado para iniciar o preparo das pizzas, conforme j´a visto anteriormente, ´e o orderPizza(), que recebe como parˆametro o sabor da pizza a ser feita.

A franquia que ir´a preparar a referida pizza ´e justamente o objeto da classe desta franquia que j´a foi previamente instanciado. Se, por exemplo, uma pizza de queijo (Che-

1 -class(pizza).

2 -export([prepare/0, bake/0, cut/0, box/0, get_name/0]). 3 4 attributes. 5 6 Name; 7 Dough; 8 Sauce; 9 Toppings. 10 11 methods. 12 13 prepare() -> 14 io:format("Preparing ~p ~n", [self::Name]), 15 io:format("Tossing dough... ~n"), 16 io:format("Adding Sauce... ~n"), 17 io:format("Adding toppings: ~n"), 18 Tops = self::Toppings, 19 prepare_aux(Tops). 20 21 prepare_aux([]) -> null; 22 prepare_aux([Top|Toppings]) -> 23 io:format(" ~p~n", [Top]), 24 prepare_aux(Toppings). 25 26 bake() ->

27 io:format("Bake for 25 minutes at 350 ~n"). 28

29 cut() ->

30 io:format("Cutting the pizza into diagonal slices ~n"). 31

32 box() ->

33 io:format("Place pizza in official PizzaStore box ~n").

C´odigo 3.4.4: Classe Pizza em ooErlang

esePizza) da franquia de Nova Iorque precisar ser preparada, ent˜ao a instˆancia da classe NYPizzaStore ir´a chamar o m´etodo orderPizza(“cheese”), onde o sabor da referida pizza ´

e passado como parˆametro. As figuras 3.8 e 3.9 mostram a execu¸c˜ao em Java e ooErlang deste exemplo.

A utiliza¸c˜ao do padr˜ao Factory Method em ooErlang mostrou-se com resultados satis- fat´orios, uma vez que foi poss´ıvel de ser implementada, assim como sua execu¸c˜ao mostrou semelhante resultado. A comprova¸c˜ao experimental da execu¸c˜ao igual em Java e em ooEr- lang valida esta extens˜ao do Erlang para ser utilizada em situa¸c˜oes nas quais este padr˜ao precise ser utilizado.

Padrão Factory Method 46

1 public class NYPizzaStore extends PizzaStore { 2

3 Pizza createPizza(String item) { 4 if (item.equals("cheese")) {

5 return new NYStyleCheesePizza(); 6 } else if (item.equals("veggie")) { 7 return new NYStyleVeggiePizza(); 8 } else if (item.equals("clam")) {

9 return new NYStyleClamPizza(); 10 } else if (item.equals("pepperoni")) { 11 return new NYStylePepperoniPizza(); 12 } else return null;

13 } 14 }

C´odigo 3.4.5: Classe NYPizzaStore em Java

1 -class(nyPizzaStore). 2 -extends(pizzaStore). 3 -export([create_pizza/1]). 4 5 methods. 6 7 create_pizza(Item) -> 8 if 9 (Item == "cheese") -> 10 Pizza = nyStyleCheesePizza::new(), 11 Pizza; 12 (Item == "veggie") -> 13 Pizza = nyStyleVeggiePizza::new(), 14 Pizza; 15 (Item == "clam") -> 16 Pizza = nyStyleClamPizza::new(), 17 Pizza; 18 (Item == "pepperoni") -> 19 Pizza = nyStylePepperoniPizza::new(), 20 Pizza; 21 true -> 22 null 23 end.

C´odigo 3.4.6: Classe NYPizzaStore em ooErlang

interface de utiliza¸c˜ao do cliente, assim como pode trabalhar com qualquer objeto concreto definido pelo usu´ario. Criar um objeto dentro de uma classe utilizando este padr˜ao ´e uma solu¸c˜ao geralmente mais flex´ıvel do que criar um objeto diretamente.

Figura 3.8: Execu¸c˜ao do exemplo para o padr˜ao Factory Method em Java.