O que é um método de "fábrica estática"?
O que é um método de "fábrica estática"?
Respostas:
Evitamos fornecer acesso direto às conexões com o banco de dados porque elas consomem muitos recursos. Portanto, usamos um método estático de fábrica getDbConnection
que cria uma conexão se estiver abaixo do limite. Caso contrário, ele tenta fornecer uma conexão "sobressalente", falhando com uma exceção se não houver.
public class DbConnection{
private static final int MAX_CONNS = 100;
private static int totalConnections = 0;
private static Set<DbConnection> availableConnections = new HashSet<DbConnection>();
private DbConnection(){
// ...
totalConnections++;
}
public static DbConnection getDbConnection(){
if(totalConnections < MAX_CONNS){
return new DbConnection();
}else if(availableConnections.size() > 0){
DbConnection dbc = availableConnections.iterator().next();
availableConnections.remove(dbc);
return dbc;
}else {
throw new NoDbConnections();
}
}
public static void returnDbConnection(DbConnection dbc){
availableConnections.add(dbc);
//...
}
}
O padrão estático do método de fábrica é uma maneira de encapsular a criação de objetos. Sem um método de fábrica, você poderia simplesmente chamar a classe construtor diretamente: Foo x = new Foo()
. Com este padrão, você iria em vez chamar o método de fábrica: Foo x = Foo.create()
. Os construtores são marcados como particulares, portanto, não podem ser chamados, exceto de dentro da classe, e o método factory é marcado como static
para que possa ser chamado sem primeiro ter um objeto.
Existem algumas vantagens nesse padrão. Uma é que a fábrica pode escolher entre muitas subclasses (ou implementadores de uma interface) e devolvê-la. Dessa forma, o chamador pode especificar o comportamento desejado por meio de parâmetros, sem precisar conhecer ou entender uma hierarquia de classes potencialmente complexa.
Outra vantagem é, como apontaram Matthew e James, controlar o acesso a um recurso limitado, como conexões. Essa é uma maneira de implementar conjuntos de objetos reutilizáveis - em vez de construir, usar e derrubar um objeto, se a construção e a destruição forem processos caros, pode fazer mais sentido construí-los uma vez e reciclá-los. O método de fábrica pode retornar um objeto instanciado existente e não utilizado, se ele tiver um, ou construir um se a contagem de objetos estiver abaixo de algum limite inferior ou lançar uma exceção ou retornar null
se estiver acima do limite superior.
Conforme o artigo da Wikipedia, vários métodos de fábrica também permitem interpretações diferentes de tipos de argumentos semelhantes. Normalmente, o construtor tem o mesmo nome que a classe, o que significa que você só pode ter um construtor com uma determinada assinatura . As fábricas não são tão restritas, o que significa que você pode ter dois métodos diferentes que aceitam os mesmos tipos de argumento:
Coordinate c = Coordinate.createFromCartesian(double x, double y)
e
Coordinate c = Coordinate.createFromPolar(double distance, double angle)
Isso também pode ser usado para melhorar a legibilidade, como observa Rasmus.
NOTA! "O método estático de fábrica NÃO é o mesmo que o padrão do Método de Fábrica " (c) Java efetivo, Joshua Bloch.
Método Factory: "Defina uma interface para criar um objeto, mas deixe as classes que implementam a interface decidirem qual classe instanciar. O método Factory permite que uma classe adie a instanciação para subclasses" (c) GoF.
"O método estático de fábrica é simplesmente um método estático que retorna uma instância de uma classe." (c) Java efetivo, Joshua Bloch. Geralmente esse método está dentro de uma classe específica.
A diferença:
A idéia principal do método estático de fábrica é obter controle sobre a criação de objetos e delegá-lo do construtor ao método estático. A decisão do objeto a ser criado é como na Abstract Factory feita fora do método (no caso comum, mas nem sempre). Enquanto a idéia-chave (!) Do Factory Method é delegar a decisão de qual instância da classe criar dentro do Factory Method. Por exemplo, a implementação clássica de Singleton é um caso especial do método estático de fábrica. Exemplo de métodos estáticos de fábrica comumente usados:
A legibilidade pode ser melhorada por métodos estáticos de fábrica:
Comparar
public class Foo{
public Foo(boolean withBar){
//...
}
}
//...
// What exactly does this mean?
Foo foo = new Foo(true);
// You have to lookup the documentation to be sure.
// Even if you remember that the boolean has something to do with a Bar
// you might not remember whether it specified withBar or withoutBar.
para
public class Foo{
public static Foo createWithBar(){
//...
}
public static Foo createWithoutBar(){
//...
}
}
// ...
// This is much easier to read!
Foo foo = Foo.createWithBar();
private Foo(boolean withBar){/*..*/}
public static Foo createWithBar(){return new Foo(true);}
public static Foo createWithoutBar(){return new Foo(false);}
- possuem nomes, diferentemente dos construtores, que podem esclarecer o código.
- não precisa criar um novo objeto em cada chamada - os objetos podem ser armazenados em cache e reutilizados, se necessário.
- pode retornar um subtipo de seu tipo de retorno - em particular, pode retornar um objeto cuja classe de implementação é desconhecida para o chamador. Esse é um recurso muito valioso e amplamente utilizado em muitas estruturas que usam interfaces como o tipo de retorno dos métodos estáticos de fábrica.
Tudo se resume à manutenção. A melhor maneira de colocar isso é que sempre que você usa a new
palavra-chave para criar um objeto, você está acoplando o código que está gravando em uma implementação.
O padrão de fábrica permite separar como você cria um objeto do que faz com ele. Quando você cria todos os seus objetos usando construtores, está essencialmente conectando o código que usa o objeto a essa implementação. O código que usa seu objeto é "dependente" desse objeto. Isso pode não parecer muito importante na superfície, mas quando o objeto muda (pense em alterar a assinatura do construtor ou em subclassificar o objeto), é necessário voltar e religar as coisas em todos os lugares.
Hoje, as fábricas foram largamente descartadas em favor do uso de injeção de dependência, porque exigem muito código de placa de caldeira que acaba sendo um pouco difícil de manter. A injeção de dependência é basicamente equivalente às fábricas, mas permite que você especifique como seus objetos são conectados de forma declarativa (por meio de configurações ou anotações).
Se o construtor de uma classe for privado, você não poderá criar um objeto para a classe de fora dela.
class Test{
int x, y;
private Test(){
.......
.......
}
}
Não podemos criar um objeto para a classe acima de fora dela. Portanto, você não pode acessar x, y de fora da classe. Então, qual é o uso dessa classe?
Aqui está o método Answer: FACTORY .
Adicione o método abaixo na classe acima
public static Test getObject(){
return new Test();
}
Então agora você pode criar um objeto para esta classe de fora dela. Desse jeito...
Test t = Test.getObject();
Portanto, um método estático que retorna o objeto da classe executando seu construtor privado é chamado como método FACTORY
.
Static Factory Method
relação ao construtor público?
Pensei em acrescentar alguma luz a este post sobre o que sei. Usamos essa técnica extensivamente em nossa recent android project
. Em vez de creating objects using new operator
você também pode usar static method
para instanciar uma classe. Listagem de código:
//instantiating a class using constructor
Vinoth vin = new Vinoth();
//instantiating the class using static method
Class Vinoth{
private Vinoth(){
}
// factory method to instantiate the class
public static Vinoth getInstance(){
if(someCondition)
return new Vinoth();
}
}
Os métodos estáticos suportam a criação condicional de objetos : toda vez que você invoca um construtor, um objeto é criado, mas você pode não querer isso. suponha que você queira verificar alguma condição apenas para criar um novo objeto. Você não criaria uma nova instância do Vinoth todas as vezes, a menos que sua condição seja satisfeita.
Outro exemplo extraído do Java eficaz .
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
Este método converte um valor primitivo booleano em uma referência de objeto booleano. O Boolean.valueOf(boolean)
método nos ilustra, nunca cria um objeto. A capacidade de static factory methods
retornar o mesmo objeto de repetidas invocations
permite que as classes mantenham controle estrito sobre quais instâncias existem a qualquer momento.
Static factory methods
é que, diferentemente constructors
, eles podem retornar um object
de qualquer subtype
tipo de retorno. Uma aplicação dessa flexibilidade é que uma API pode retornar objetos sem tornar suas classes públicas. Ocultar classes de implementação dessa maneira leva a uma API muito compacta.
Calendar.getInstance () é um bom exemplo para o acima, cria-se, dependendo da localidade um BuddhistCalendar
, JapaneseImperialCalendar
ou por um padrão Georgian
.
Outro exemplo que eu poderia pensar é Singleton pattern
: onde você torna seus construtores privados, cria um getInstance
método próprio , onde você garante que sempre haja apenas uma instância disponível.
public class Singleton{
//initailzed during class loading
private static final Singleton INSTANCE = new Singleton();
//to prevent creating another instance of Singleton
private Singleton(){}
public static Singleton getSingleton(){
return INSTANCE;
}
}
Um método de fábrica, um método que abstrai a instanciação de um objeto. Geralmente as fábricas são úteis quando você sabe que precisa de uma nova instância de uma classe que implemente alguma interface, mas não conhece a classe de implementação.
Isso é útil ao trabalhar com hierarquias de classes relacionadas, um bom exemplo disso seria um kit de ferramentas da GUI. Você pode simplesmente codificar as chamadas aos construtores para implementações concretas de cada widget, mas se você quiser trocar um kit de ferramentas por outro, terá muitos lugares para mudar. Ao usar uma fábrica, você reduz a quantidade de código que precisaria alterar.
Uma das vantagens que resulta da fábrica estática é que essa API pode retornar objetos sem tornar suas classes públicas. Isso levou a uma API muito compacta. Em java, isso é alcançado pela classe Collections, que oculta cerca de 32 classes, o que a torna muito compacta.
Um método estático de fábrica é bom quando você deseja garantir que apenas uma única instância retorne a classe de concreto a ser usada.
Por exemplo, em uma classe de conexão com o banco de dados, convém que apenas uma classe crie a conexão com o banco de dados, de modo que, se você decidir mudar do Mysql para o Oracle, poderá alterar a lógica de uma classe e o restante do aplicativo irá use a nova conexão.
Se você deseja implementar o pool de banco de dados, isso também seria feito sem afetar o restante do aplicativo.
Ele protege o restante do aplicativo das alterações que você pode fazer na fábrica, que é a finalidade.
O motivo para ser estático é que, se você deseja acompanhar algum recurso limitado (número de conexões de soquete ou identificadores de arquivo), essa classe pode acompanhar quantos foram desmaiados e retornados, para não esgotar o recurso limitado.
Uma das vantagens dos métodos estáticos de fábrica com o construtor privado (a criação de objetos deve ter sido restrita a classes externas para garantir que as instâncias não sejam criadas externamente) é que você pode criar classes controladas por instância . E as classes controladas por instância garantem que não existem duas instâncias distintas iguais ( a.equals (b) se e somente se a == b ) durante a execução do programa, significa que você pode verificar a igualdade de objetos com o operador == em vez do método equals , de acordo com java eficaz.
A capacidade dos métodos estáticos de fábrica de retornar o mesmo objeto a partir de invocações repetidas permite que as classes mantenham controle rígido sobre quais instâncias existem a qualquer momento. Diz-se que as classes que fazem isso são controladas por instância. Há vários motivos para escrever classes controladas por instância. O controle de instância permite que uma classe garanta que é um singleton (Item 3) ou não instável (Item 4). Além disso, permite que uma classe imutável (Item 15) garanta que não existem duas instâncias iguais: a.equals (b) se e somente se a == b. Se uma classe faz essa garantia, seus clientes podem usar o operador == em vez do método equals (Object), o que pode resultar em melhor desempenho. Os tipos enum (Item 30) fornecem essa garantia.
De Java eficaz, Joshua Bloch (Item 1, página 6)
estático
Um membro declarado com a palavra-chave 'estático'.
métodos de fábrica
Métodos que criam e retornam novos objetos.
em Java
A linguagem de programação é relevante para o significado de 'estático', mas não para a definição de 'fábrica'.
A implementação Java contém as classes de utilitários java.util.Arrays e java.util.Collections, ambas contêm métodos estáticos de fábrica , exemplos e como usar:
Arrays.asList("1","2","3")
Collections.synchronizedList(..), Collections.emptyList(), Collections.unmodifiableList(...)
(Apenas alguns exemplos, você pode verificar exemplos de métodos mor no javadocs https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html )
A classe java.lang.String também possui métodos estáticos de fábrica :
String.format(...), String.valueOf(..), String.copyValueOf(...)