No último artigo, eu comecei a falar sobre o Padrão de Projeto Factory, que cria objetos para você, em geral, todos os que seguem a mesma interface. Até agora, nós fizemos o Simple Factory, que cria essa funcionalidade em um objeto Singleton, que é a maneira mais simples de criar um Factory, daí a sua nomenclatura (adoro essa palavra). Desta vez, eu vou te mostrar o Factory de verdade.
O que é o Factory de verdade?
O padrão Factory real é diferente do Simple Factory porque ao invés de usar um objeto separado para criar os cars (no meu exemplo do Decorador), ele usa subclasses. A forma oficial para descrever o padrão Factory seria mais ou menos assim: “uma classe que difere instanciação de seus objetos membros para uma subclasse.”
Exemplo Car Shop Factory
Para este exemplo, ficarei com o tema do car e vou até mesmo continuar usando o Car e seus decorators, que estabeleci no artigo do padrão Decorator. Entretanto, adicionarei alguns modelos de cars para misturar as coisas e ajudar a mostrar como isso realmente funciona. Não se preocupe, eles só fazem uma subclasse a partir do Car, e por uma questão de manter o código conciso e por isso não ter importância, nem vou mostrar-lhe a implementação dessas classes.
Começaremos com um car shop (chamado CarShop de todas as coisas). Esse é o local de onde pegaremos nossos carros, pois nenhuma pessoa esperta compra um carro da fábrica (apesar de que, neste exemplo, CarShop passa a ser de fato uma fábrica). CarShop na verdade não é um objeto que possamos usar por ele mesmo; é essencialmente uma classe abstrata, pois implementa algumas funcionalidades, mas não pode ser iniciado, pois deixa algumas funcionalidades para serem implementadas pelas subclasses. Dá uma olhada:
/* Abstract CarShop "class" */
var CarShop = function(){};
CarShop.prototype = {
sellCar: function (type, features) {
var car = this.manufactureCar(type, features);
getMoney(); // make-believe function
return car;
},
decorateCar: function (car, features) {
/*
Decorate the car with features using the same
technique laid out in CarFactory on my previous
post:
http://www.joezimjs.com/javascript/javascript-design-patterns-factory/
*/
},
manufactureCar: function (type, features) {
throw new Error("manufactureCar must be implemented by a subclass");
}
};
Viu o método decorateCar? Ele é essencialmente o mesmo método do artigo anterior do padrão Factory: CarFactory.makeCar, exceto que ele recebe o objeto Car normal como um argumento em vez de instanciá-lo. Note também que o manufactureCar é definido, mas isso só gera um erro? Cabe às subclasses implementar esse método. Isso também ocorre por ser o método factory. Agora vamos fazer um car shop específico que implemente manufactureCar.
/* Subclass CarShop and create factory method */
var JoeCarShop = function() {};
JoeCarShop.prototype = new CarShop();
JoeCarShop.prototype.manufactureCar = function (type, features) {
var car;
// Create a different car depending on what type the user specified
switch(type) {
case 'sedan':
car = new JoeSedanCar();
break;
case 'hatchback':
car = new JoeHatchbackCar();
break;
case 'coupe':
default:
car = new JoeCoupeCar();
}
// Decorate the car with the specified features
return this.decorateCar(car, features);
};
Essa loja só vende carros da marca Joe, portanto, seu método factory tem que ser diferente de outras lojas que vendem outros tipos de carros como este a seguir, que só vende veículos da marca Zim.
/* Another CarShop and with factory method */
var ZimCarShop = function() {};
ZimCarShop.prototype = new CarShop();
ZimCarShop.prototype.manufactureCar = function (type, features) {
var car;
// Create a different car depending on what type the user specified
// These are all Zim brand
switch(type) {
case 'sedan':
car = new ZimSedanCar();
break;
case 'hatchback':
car = new ZimHatchbackCar();
break;
case 'coupe':
default:
car = new ZimCoupeCar();
}
// Decorate the car with the specified features
return this.decorateCar(car, features);
};
Usando seus Car Shops
Abaixo, você verá como você usaria esses recém-criados car shops. Pessoalmente, não acho que seja tão legal quanto um Simple Factory, mas se você estiver se sentindo um aventureiro, pode sempre fazer um Simple Factory para criar as lojas para você. Então, você empilhará Factories como um profissional!
// Use Joe's Shop
var shop = new JoeCarShop();
var car = shop.sellCar("sedan", ['powerlocks']);
// How about the Zim Shop? Same thing
shop = new ZimCarShop();
car = shop.sellCar("sedan", ['powerlocks']);
// The shop determines which type of Car we get,
// even if we give the same parameters
Conclusão
Isso encerra o padrão Factory (de verdade dessa vez). Espero que tenha aprendido alguma coisa, caso contrário, estou perdendo o sono sem motivo e você está desperdiçando seu tempo.
?
Texto original disponível em http://www.joezimjs.com/javascript/javascript-design-patterns-factory-part-2/







