Metodos Factory?

Alguém tem uma boa definição para metodos de fabrica? Pra clarear minhas idéias…

De maneira simples, é um método que tem como objetivo criar outros objetos.

Não confundir com o padrão “Abstract Factory”.

Boa não sei se é , mas … eu uso esta

Eles ajudam na hora de você não precisar definir todos parâmetros para o construtor da classe. Ajudam bastante quando você já tem valores pré-moldados.

[code]Carro carro = new Carro()
.montadora(VOLKSWAGEN)
.carro(GOLF)
.modelo(GTI)
.roda(LIGA_LEVE)
.aro(17)
.portas(4)
.cilindrada(1.8)
.airBag()
.trioEletrico()
.arCondicionado()
.tetoSolar();

// Se você usar a configuração acima toda hora,
// é mais fácil dizer
Carro carro = VolksWagenFactory().GOLF_GTI_COMPLETO;
// e completar com adicionais;
carro = carro
.cor(PRATA)
.banco(COURO);

// AbstractFactory nesse caso seria um CarroFactory
// em que um dos métodos retornasse VolksWagenFactory[/code]

1 curtida

[quote=renrutal]Eles ajudam na hora de você não precisar definir todos parâmetros para o construtor da classe. Ajudam bastante quando você já tem valores pré-moldados.

[code]Carro carro = new Carro()
.montadora(VOLKSWAGEN)
.carro(GOLF)
.modelo(GTI)
.roda(LIGA_LEVE)
.aro(17)
.portas(4)
.cilindrada(1.8)
.airBag()
.trioEletrico()
.arCondicionado()
.tetoSolar();

// Se você usar a configuração acima toda hora,
// é mais fácil dizer
Carro carro = VolksWagenFactory().GOLF_GTI_COMPLETO;
// e completar com adicionais;
carro = carro
.cor(PRATA)
.banco(COURO);

// AbstractFactory nesse caso seria um CarroFactory
// em que um dos métodos retornasse VolksWagenFactory[/code][/quote]

Vc descreveu dois outros padrões diferentes: no primeiro codigo é o Builder e no segundo é o Prototype (um objeto que já tem o o básico e depois vc edita o que mais quiser) . Em nenhum dos dois exemplo está sendo usado Factory Method

Nunca falei que o primeiro era uma Factory Method, disse isso do segundo.

Prototype não é um tipo de Factory Method? Ele encapsula a criação de um objeto em um método.

Pessoal, não se implementa Factory Method simplesmente criando um método na sua classe que crie o objeto para você.

Tomem o exemplo abaixo:

public class Dog { // É esse método que vocês chamam de Factory Method? public Dog getInstance() { return new Dog(); } }
Usando a forma acima, o máximo que conseguimos abstrair aqui são os detalhes da criação da instância. A idéia do Factory Method é fornecer uma interface para criação de famílias de objetos sem especificar suas classes concretas. Refatorando o exemplo anterior para aplicar o Factory Method, teríamos:

[code]
// “Família” do produto a ser criado
public abstract class Animal {

}

// Produto concreto a ser criado ( exemplo )
public class Dog extends Animal {

}

// Fábrica abstrata
public abstract class Factory {
public Animal factoryMethod();
}

// Fábrica concreta, que criará instâncias de Dog.
public class DogFactory extends Factory {
public Animal factoryMethod() {
return new Dog(); // A acoplação existe somente aqui!
}
}[/code]
O que conseguimos aqui? Conseguimos não somente abstrair os detalhes da criação do objeto, como também o tipo do objeto em si. Mas um dos grandes lances do Factory Method é quando você precisa estender sua API de fabricação. Se por acaso precisarmos de uma fábrica de gatos:

[code]public class Cat extends Animal {

}

public class CatFactory extends Factory {
public Animal factoryMethod() {
return new Cat();
}
}[/code]
Todo padrão tem situações específicas onde se aplica. Há situações que precisamos implementar um Factory Method, e há situações que precisamos apenas de um método que cria uma instância do objeto para nós. Mas não chamem esse método de Factory Method.

Abraços

Obrigado…

Obrigado tnaires, estava precisando de uma explicação mais detalhada.

[quote=tnaires]Pessoal, não se implementa Factory Method simplesmente criando um método na sua classe que crie o objeto para você.

Tomem o exemplo abaixo:

public class Dog { // É esse método que vocês chamam de Factory Method? public Dog getInstance() { return new Dog(); } }
Usando a forma acima, o máximo que conseguimos abstrair aqui são os detalhes da criação da instância. A idéia do Factory Method é fornecer uma interface para criação de famílias de objetos sem especificar suas classes concretas. Refatorando o exemplo anterior para aplicar o Factory Method, teríamos:

[code]
// “Família” do produto a ser criado
public abstract class Animal {

}

// Produto concreto a ser criado ( exemplo )
public class Dog extends Animal {

}

// Fábrica abstrata
public abstract class Factory {
public Animal factoryMethod();
}

// Fábrica concreta, que criará instâncias de Dog.
public class DogFactory extends Factory {
public Animal factoryMethod() {
return new Dog(); // A acoplação existe somente aqui!
}
}[/code]
O que conseguimos aqui? Conseguimos não somente abstrair os detalhes da criação do objeto, como também o tipo do objeto em si. Mas um dos grandes lances do Factory Method é quando você precisa estender sua API de fabricação. Se por acaso precisarmos de uma fábrica de gatos:

[code]public class Cat extends Animal {

}

public class CatFactory extends Factory {
public Animal factoryMethod() {
return new Cat();
}
}[/code]
[/quote]

Acho que é obvio a qualquer um que vc está implementando Factory. Até porque vcestá estendendo um classe chamada factory cuja responsabildiade é criar objetos.

E sim, o Factory Method é apenas um método que cria o objeto. Normalmente isso é feito com new, mas pode ser feito por reflectino, por exemplo.

Não confundir Factory Method com Factory com Abstract Factory. São 3 padrões diferentes embora muito proximos.

P.S. Collection.iterator () é um exemplo de Factory Method presente na API padrão do Java

[quote=renrutal]
Prototype não é um tipo de Factory Method? Ele encapsula a criação de um objeto em um método.[/quote]

Prototype não é um tipo de Factory Method já que ele não é obrigado a encapsular a criação do objeto em métodos. O objeto, já está criado é sempre o mesmo. Dai o nome Prótotipo.

Prototipo pode ser usado por um Factory , Factroy Method ou Abstract Factory, mas seus objetivos são diferentes.
Enquanto a familia factory está preocupada em dicidir qual objeto instancializar Prototype já sabe qual é o objeto e quais os valores padrão para os seus atributos.

O padrão Prototype pode ter um Factory Method que apenas clona o objeto e devolve, ou pode ser usado numa Factory para fazer o mesmo.

[quote=sergiotaborda]Acho que é obvio a qualquer um que vc está implementando Factory. Até porque vcestá estendendo um classe chamada factory cuja responsabildiade é criar objetos.

E sim, o Factory Method é apenas um método que cria o objeto. Normalmente isso é feito com new, mas pode ser feito por reflectino, por exemplo.

Não confundir Factory Method com Factory com Abstract Factory. São 3 padrões diferentes embora muito proximos.

P.S. Collection.iterator () é um exemplo de Factory Method presente na API padrão do Java[/quote]
Não, isso não é Factory ( de onde saiu esse padrão? Referências? ), é Factory Method.

Sérgio, o padrão Factory Method da forma como descrevi no post anterior é exatamente a forma como está ilustrada no livro da gangue dos quatro ( vide exemplo do framework de criação de múltiplos documentos para o usuário ). Além disso, o capítulo sobre fábricas do livro Head First Design Patterns começa justamente descrevendo o erro comum que os desenvolvedores cometem de achar que Factory Method é um simples método que dá new no objeto ( o livro chama essa prática de Single Factory ).

Hmmm… Deixe-me só retificar algumas coisas. Concordo com você, Sérgio, que o nome do método utilizado para instanciar os objetos é factory method ( inclusive, foi a nomenclatura que utilizei no exemplo que postei ). Mas o que eu estou tentando dizer é: para implementar o padrão Factory Method ( repare as letras maiúsculas ), não basta criar um factory method ( repare as letras minúsculas ): é preciso abstrair do cliente o tipo concreto do objeto que ele está criando. Ou seja, ele trabalha apenas com sua abstração, não com seu tipo concreto. Sacou?

[quote=tnaires][quote=sergiotaborda]Acho que é obvio a qualquer um que vc está implementando Factory. Até porque vcestá estendendo um classe chamada factory cuja responsabildiade é criar objetos.

E sim, o Factory Method é apenas um método que cria o objeto. Normalmente isso é feito com new, mas pode ser feito por reflectino, por exemplo.

Não confundir Factory Method com Factory com Abstract Factory. São 3 padrões diferentes embora muito proximos.

P.S. Collection.iterator () é um exemplo de Factory Method presente na API padrão do Java[/quote]
Não, isso não é Factory ( de onde saiu esse padrão? Referências? ), é Factory Method.
[/quote]

Referencias

Se vc decide chamar o Factory de Factory Method tudo bem. O problema é seu. Mas repare na ilogicidade dessa escolha. Se o factroy é um objeto como chamá-lo de “método” não faz sentido algum.
Qual é o problema em entender que “Method” significa “método” e Factory Method significa “método de fabrica” ( ou “método de fabricação” conforme tradução) Nunca Factory Método implica em objetos do tipo fabrica!

Ha uma logica nos nomes e responsabilidades diferentes.
Como eu citei antes Collection.iterator() é um exemplo de Factory Method, mas não é um exemplo de Factory.

Por isso eu falo no meu blog da relação entre Factory Method e Factory e começo o texto dizendo
"Factory Method é provavelmente um dos padrões mais utilizados porque ele é muito natural. Ele é usado, muitas vezes, sem consciencia de que está sendo usado um padrão." Acho que está sendo o caso aqui.

Também falo sobre como Factory é a adição de polimorfismo a Factory Method já que promove o uso de Herança.

Factories e muitos outros objetos contém Factory Methods (Collection, Locale, Currency , só para citar alguns)
Mas o inverso não é verdade. Collection não é um Factory , nem Locale… etc.

A diferenciação é necesária porque senão não ha nome para os métodos como “iterator()” em objetos como Collection.

Você é livre de pensar e analizar a mesma bibliografia que eu. E não o obrigo a tirar as mesmas conclusões que eu. Eu só não posso aceitar que Factory Method e Factory sejam o mesma padrão por motivos apenas logicos

“Todos os objetos Factory são especilizações de Factory Method” não implica que "Todos as especilizações de Factory Method são objetos Factory " porque me basta um exemplo para contrariar a segunda afirmação Collection.iterator()

Se não consegue ver a logica nisto, tudo bem. Só peço que não tenha raiva de mim, se consigo. :wink:

[quote=tnaires]Hmmm… Deixe-me só retificar algumas coisas. Concordo com você, Sérgio, que o nome do método utilizado para instanciar os objetos é factory method ( inclusive, foi a nomenclatura que utilizei no exemplo que postei ).
[/quote]

Como disse, não o brigo a concordar. Mas já que concorda, otimo :lol: 8)

[quote]
Mas o que eu estou tentando dizer é: para implementar o padrão Factory Method ( repare as letras maiúsculas ), não basta criar um factory method ( repare as letras minúsculas ): é preciso abstrair do cliente o tipo concreto do objeto que ele está criando. Ou seja, ele trabalha apenas com sua abstração, não com seu tipo concreto. Sacou?[/quote]

Não necessáriamente. A responsabildiade de criar m objeto não se limita a dar new nele. Na realidade criar um objeto significa “criar um objeto em estado consistente” Nem sempre é possivel criar um estado consistente apenas usando construtor. (Por exemplo quando ha refeencias ciclicas)

Portanto um método como este

public Objecto blablabla(){
     return new Objecto();
}

é tecnicamente um factory method porque “cria um objeto em estado consistente”. no caso, basta invocar o construtor para ter um estado consistente. Mas poderia não ser assim , pro exemplo

public Objecto blablabla(){
     Objecto obj = new Objecto();
      ObjetoB b = new ObjetoB(obj);
       obj.b = b;
    return obj;
}

Outra opção é fazer assim

public Objecto blablabla(){
     return new ObjectoQueExtendeObjeto();
}

De fora continua sendo Objeto, mas internamente ha polimorfismo envolvido.

Como o factory méthod é um encapsulação é irrelevante como ele é implementado. O ponto é que haja um método responsável por criar um objeto em estado consistente.

Claro que vc pode usar Interfaces, etc… e abstrair ainda mais o tipo de objeto retornado (como faz Collection.iterator) mas isso é um detalhe. É um upgrade da implementação do padrão. Não é o padrão em si.

Antes de mais nada Sérgio, não há necessidade de achar que essa discussão é pessoal. Você poderia evitar comentários do tipo:

Eu fico sem saber se você fala sério ou brincando, pois suas reações a contestações já são conhecidas pelo pessoal do GUJ.

Quando pedi referências, queria que você me mostrasse onde você tinha visto esse padrão Factory, pois só conheço Factory Method e Abstract Factory. Mas agora entendo que Factory é só o nome do objeto responsável por fabricar as instâncias. Meu erro foi pensar que se tratava de um padrão.

Realmente, podemos ler as mesmas biografias e tirar diferentes conclusões. Mas eu procuro me ater ao que está escrito, e não deduzir coisas. Se a gangue dos quatro afirmou que para usar o padrão ( e não o método ) chamado Factory Method eu preciso de quatro classes ( e não simplesmente criar um factory method e dizer que estou usando Factory Method ), quem sou eu ( ou você ) pra achar diferente?

Sinceramente, nunca vi isso. Não conheço Factory Method sem o uso de herança. Realmente não sei de onde você tirou essa definição. Se você me mostrar uma fonte confiável que afirme que implementar o padrão Factory Method é só escrever um método que faça um new numa classe, eu fico calado.

[editado]
ups… acabei escrevendo por cima do que tinha escrito… foi mal.
Se for possivel aos moderadores retornarem o texto original, por favor , façam-o
[/editado]

[quote=sergiotaborda]A ideia é “odeie a mensagem não o mensageiro”. Exactamente para não tornar a discussão pessoal.
As minhas reações advêm de anos praticando discussão online e sei reconhecer argumentos de autoridade. E sei reconhecer que isso cai muito facilmente para ataques ad-hominem. Então, antes que isso aconteça, ficou a resalva. O meu objetivo é vincular informação e não ha necessidade que ninguem concorde com ela, mas ha necessidade que a pessoa entenda o que estou dizendo. Entender =/= Aceitar. Por isso parece que repito, mas isso é apenas porque o que eu disse não foi entendido.[/quote]
Eu só questiono o fato de atacar antes que o ataque exista, mas compreendo seu ponto.

[quote=sergiotaborda]Eu não estou em casa, posso colocar depois, mas existem referencia a isso sim.
Entretando, vc leu alguma referencia do google ?

Exemplo de Factory Method estático, o mais comum.
http://www.javaworld.com/javaworld/javaqa/2001-05/02-qa-0511-factory.html

Novamente o Factory Method estatico com uma resalva a porque o padrão do GoF está desatualizado
http://home.earthlink.net/~huston2/dp/factory_method.html[/quote]
Eu tinha lido o artigo do Java World. E veja que, em ambos, o factory method retorna uma abstração. Se eu usar um factory method para retornar uma implementação, eu não estou usando o padrão Factory Method em si ( pelo menos não da forma como é amplamente aceito ). Esse é o ponto que venho enfatizado nos meus posts.

[quote=sergiotaborda]Essa frase tem várias falacias. O seu argumento não passa. Não esse tipo de argumento.
Primeiro o Gof escreveu padrões em C++. Por muito que Java seja semelhante não é a mesma coisas.Por outro lado isso foi à mais de 10 anos. Acho que podemos evoluir um pouco nesse tempo.
Quem somos nós para pensar diferente ? ora, somos nós mesmos. Acaso existe algum tipo de censura que nos impede pensar mais e/ou melhor sobre algum assunto ? Acaso o que foi escrito é incontestável ? algum tipo de biblia sagrada ? Concerteza não. A lógica é muitos mais relevante aqui do que qualquer tipo de escritos. Seja por quem for. O que eu esperava era uma critica construtiva. Primeiro entender que existe uma diferença logica, de responsabilidade e até linguistica entre “Factory” e “Factory Method”. Segundo entender que isso é razão suficiente para desconfiar que existem dois padrões. Terceiro discutir o que propuz do ponto de vista de OO, java ou qualquer outro que não sob o ponto de vista de argumentos de autoridade pela citação de bibliografia.
Agora que vc entender que eles existem e são diferentes, o que vc acha dos livros que vc citou ?

Os livros não são completos em si mesmos. Apenas pela conjução de vários e pela critica de cada um e do conjunto poderemos chegar numa conclusão melhor. Quem somos nós para chegar numa conclusão melhor ? Ora, somos tão capazes como quaisquer outros.[/quote]
Realmente, fui infeliz ao afirmar que não podemos questionar aquilo que foi escrito. Mas eu estava apenas tentando me prender ao conceito. Se eles definiram dessa forma, e está amplamente aceito, então qualquer interpretação diferente corre o risco de ser tachada de errada.
Sobre os livros, concordo que alguns conceitos do livro do GoF podem estar demais atrelados à “linguagem vigente” na época. Mas o outro livro que citei ( Head First Design Patterns ) é relativamente atual e conserva a definição do padrão Factory Method ( e ainda comenta esse conceito confundido pelos desenvolvedores ).

[quote=sergiotaborda]Normalmente quando me pedem esse tipo de coisas eu mando a pessoa passear porque “is missing the point”.
O ponto não é se Factory Method é ou não citado em livros. O ponto é se ele é realmente outro padrão.
Já lhe citei exemplos como Collection.iterator(). collection não é um factory de iteradores, contudo ela contém um método que encapsula a criação de iteradores.
No seu caso eu vou abrir uma exceção. Eu posto depois a referencia a um livro com esse padrão…[/quote]
Ok, no aguardo.

Olhando o livro “Padrões de Projeto em Java”, Steve Metsker fala um pouco sobre como reconhecer um Factory Method, ele:

:arrow: Cria um novo objeto;
:arrow: O tipo de retorno é uma classe abstrata ou uma interface
:arrow: É implementado por diversas classes

Com isso ele dá vários exemplos:

A classe BorderFactory tem muitos métodos que criam objetos, mas nenhum deles é uma Factory Method, somente a classe mesmo é uma Factory.

O Arrays.asList cria um objeto e retorna uma interface, mas é implementado somente lá, não é encontrado em outras classes pois não é necessário.

O método toString de qualquer objeto, cria um objeto, e é encontrado em todo lugar, mas não abstrai a implementação, retorna sempre a classe String.

Por último, o método iterator encontrado na interface Collection. Ele cria objetos que obedecem à interface Iterator, é encontrado consistentemente nas Collections, é altamente coeso sobre o que faz, e abstrai sua implementação interna, os clientes desse método não sabem quem estão instanciando, mas sabem que é um Iterator, o que é suficiente.

Steve também fala que o Factory Method é útil na aplicação de hierarquia de classes paralelas, assim como o Collection tem seu Iterator, ArrayList tem seu Iterator interno, LinkedList tem seu próprio, HashSet também o seu, sem falar das outras.

Bom, a referencia bibliográfica…

Design Patterns Java Workbook
Steven John Metsker
2002 Pearson Education, Inc

Claro agora ? :wink:

Quanto ao argumento de que só é um factory method se retornar algo abstracto. à primeira vista pode parecer coerente que não haja objetivo em retornar um objecto instanciável de dentro de um método.
Isso parece querer forçar a definição para só aceitar o nome se o retorno for abstrato. Mas o que é ser abstrato para um método que encapsula uma criação ? Só porque é interface ou abstract class quer dizer que é abstrato ?

public Object instanciate();

Que tal esse, abstrato o suficiente ? Mesmo assim eu posso fazer new Object se quiser…
A abstração não é programática com interfaces e classe abstratas ( embora muitas vezes isso seja verdade, mas por causa do principio de programar para interfaces e não por causa do padrão Factroy Method) O ponto é que o cliente não sabe o estado do objeto que virá do método. E isso é que é encapsulamento. Ou melhor dito, se usar interface ou classe abstrata vc está fazendo um duplo encapsulamento, está encapsulando a criação e o tipo especifico de objeto. Mas o padrão só tem a haver com o primeiro encapsulamento. Na prática não utilizar o segundo é inutil, mas existem casos em que não é inutil e por isso que é que não podemos reduzir as coisas a só aceitar se houver interfaces no meio da historia. A abstração está na responsabilidade do objeto cliente e no conhecimento que ele tem do interior do método chamado.

O StringBuffer e o StringBuilder implementam o padrão Builder. Este padrão é muito próximo do Factory Method porque sempre ha um método no builder que constroi o objeto real. No caso é o método toString() criando objetos String. Eu posso dar new String quando quiser, mas o ponto do factory method é não só fazer o new mas colocar o objeto em estado consistente antes de me o devolver. Consistente significa que o objeto terá um estado com significado para que o obtém. Portanto, nem toda a string seria válida.
Em particular, o Builder constroi o estado em vários passos para depois o devolver na chamada ao Factory method. O Builder contém um Factory Method que cria um objeto,o instancializa e seta seu estado. Mas o objeto não é abstrato nem um interface. Significa isso que não ha Factory Method envolvido ? Na minha opinião não significa.

Claro que poderia argumentar que se é Builder não é Factory Method, mas ai que está a graça deste padrão é o padrão para um método. À semelhança de Template Method é um padrão que fala sobre a responsabilidade de um método e não de um classe. Logo ele pode ser incluso em outras classes e em implementações de outro padrões sem deixar de ser ele mesmo. Isso é muito poderoso. Tanto que muita gente nem dá pela presença destes dois padrões.