Classes de fábrica [fechadas]

Pessoalmente, nunca compreendi a ideia das classes fabris porque parece muito mais útil apenas instanciar um objecto directamente. Minha pergunta é simples, em que situação é o uso de um padrão de classe de fábrica a melhor opção, por que razão, e como se parece uma boa classe de fábrica?

Author: sepp2k, 2013-01-29

7 answers

A ideia aqui é a separação de preocupações: se o código que usa o objecto também tem informação suficiente para o instanciar, você não precisa de uma fábrica. No entanto, se houver alguma lógica ou configuração envolvida que você não quer ter o usuário da API para pensar (ou mexer com), você pode esconder tudo isso (e encapsulá-lo para reutilização) em uma fábrica.

Aqui está um exemplo: você quer acessar um dos Serviços fornecidos pelo Google App Engine. O mesmo código deve funcionar em ambos os ambiente de desenvolvimento (do qual existem duas versões, master-slave e high-availabilty) e o ambiente de desenvolvimento local completamente diferente. O Google não quer falar sobre o funcionamento interno de sua infraestrutura interna, e você realmente não quer saber. Então o que eles fazem é fornecer interfaces e fábricas (e várias implementações dessas interfaces para as fábricas escolherem a partir do que você nem precisa saber).

 26
Author: Thilo, 2013-01-29 04:06:02
Aqui está uma verdadeira fábrica ao vivo da minha base de códigos. É usado para gerar uma classe de sampler que sabe como amostrar dados de algum conjunto de dados (é originalmente em C#, então desculpe qualquer falha java-pas)
class SamplerFactory
{
  private static Hashtable<SamplingType, ISampler> samplers;

  static
  {
    samplers = new Hashtable<SamplingType, ISampler>();
    samplers.put(SamplingType.Scalar, new ScalarSampler());
    samplers.put(SamplingType.Vector, new VectorSampler());
    samplers.put(SamplingType.Array, new ArraySampler());
  }

  public static ISampler GetSampler(SamplingType samplingType)
  {
    if (!samplers.containsKey(samplingType))
      throw new IllegalArgumentException("Invalid sampling type or sampler not initialized");
    return samplers.get(samplingType);
  }
}

E aqui está um exemplo de Utilização:

ISampler sampler = SamplerFactory.GetSampler(SamplingType.Array);
dataSet = sampler.Sample(dataSet);
Como vês, não é muito código, e pode até ser mais curto e mais rápido só de fazer
ArraySampler sampler = new ArraySampler();
dataSet = sampler.Sample(dataSet);

Do que usar a fábrica. Então porque me dou ao trabalho? Bem, há duas razões básicas, que se baseiam em cada outros:

  1. Primeiro, é a simplicidade e a manutenção do Código. Digamos que no código de chamada, o enum é fornecido como um parâmetro. Ou seja, se eu tivesse um método que precisasse de processar os dados, incluindo a amostragem, eu poderia escrever:
    void ProcessData(Object dataSet, SamplingType sampling)
    {
      //do something with data
      ISampler sampler = SamplerFactory.GetSampler(sampling);
      dataSet= sampler.Sample(dataSet);
      //do something other with data
    }
    
    Em vez de uma construção mais pesada, como esta:
    void ProcessData(Object dataSet, SamplingType sampling)
    {
      //do something with data
      ISampler sampler;
      switch (sampling) {
        case SamplingType.Scalar:  
          sampler= new ScalarSampler();
          break;
        case SamplingType.Vector:  
          sampler= new VectorSampler();
          break;
        case SamplingType.Array:
          sampler= new ArraySampler();
          break;
        default:
          throw new IllegalArgumentException("Invalid sampling type");
      }
      dataSet= sampler.Sample(dataSet);
      //do something other with data
    }
    
    Note que esta monstruosidade deve ser escrita sempre que preciso de amostras. E você pode imaginar como será divertido mudar se, vamos eu adicionei um parâmetro ao construtor, ou adicionei um novo. E esta fábrica tem apenas três opções agora, imagine uma fábrica com 20 implementações.
  2. Segundo, é a dissociação do Código. Quando eu uso uma fábrica, o código de chamada não sabe ou precisa saber que uma classe chamada ArraySampler mesmo existe. A classe poderia até ser resolvida em tempo de execução, e o local de chamada não seria o mais sábio. Portanto, consequentemente, sou livre para mudar a classe ArraySampler o quanto eu quiser., incluindo, mas não limitado a, a exclusão definitiva da classe, se, por exemplo, eu decidir que o ScalarSampler deve ser usado para dados array também. Só preciso de mudar a linha.
    samplers.put(SamplingType.Array, new ArraySampler());
    

    A

    samplers.put(SamplingType.Array, new ScalarSampler());
    
    E funcionaria magicamente. Não tenho de alterar uma única linha de código nas aulas de chamada, que poderia ser de centenas. Efetivamente, a fábrica me faz controlar o que e como a amostragem ocorre, e quaisquer mudanças de amostragem são eficientemente encapsuladas dentro de um único classe de fábrica que está conectado com o resto do sistema.
 50
Author: SWeko, 2014-01-01 06:06:09

Pessoalmente, eu uso o padrão de fábrica quando a implementação de uma interface é desconhecida no tempo de execução, ou pode ser feita dinâmica.

Isso significa que como desenvolvedor, eu trabalho contra uma interface conhecida para a instância do objeto, mas não estou preocupado com a forma como a implementação funciona.

Por exemplo. Você poderia usar um padrão de fábrica para lhe fornecer objetos de uma base de dados. Você não se importa se essa base de dados é um arquivo Plano, Base de dados local/único usuário, servidor banco de dados ou recurso web, apenas que a fábrica pode gerar e gerenciar esses objetos. Odeio ter de escrever implementações para cada um desses casos.
 4
Author: MadProgrammer, 2013-01-29 04:08:05

Do eficaz livro Java de Joshua Bloch, parcialmente reescrito por mim:

1) Os métodos estáticos de fábrica (SFM), ao contrário dos construtores, têm nomes.

public static ComplexNumber one () {
    return new ComplexNumber(1, 0);
}

public static ComplexNumber imgOne () {
    return new ComplexNumber(0, 1);
}

public static ComplexNumber zero () {
    return new ComplexNumber(0, 0);
}

2) não é necessário criar um novo objecto cada vez que SFM é / são invocados

public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE; 
}

3) SFM pode devolver um objeto de qualquer subtipo do seu tipo de retorno.

4) SFM reduza a verbosidade da criação de instâncias de tipo parametrizado.

public static <K, V> HashMap<K, V> newInstance() {
    return new HashMap<K, V>();
}

Map<String, List<String>> m = HashMap.newInstance();
 4
Author: Nikolay Kuznetsov, 2017-09-26 19:56:23

Para complementar a resposta de Thilo, vamos supor que você tem um objeto que só tem um booleano como um construtor: seria um desperdício total construir um de cada vez, uma vez que ele só tem dois valores possíveis.

Neste caso, você pode criar métodos de fábrica estáticos. A classe Boolean do Java é um exemplo: Boolean.valueOf().
 1
Author: fge, 2013-01-29 04:08:19
A fábrica por si só não mostra a sua beleza tão facilmente. É quando você combina com outros padrões quando você vê os benefícios reais, por exemplo, se você quiser usar o padrão do decorador, instanciar um objeto diretamente pode adicionar algum acoplamento adicional ao seu código. Como diz O Professor de OOP, acoplamento é ruim: ) assim, se você fosse para instanciar o objeto decorado e não queria aumentar Acoplamento, então você poderia usar uma fábrica.
 0
Author: Juan Alberto López Cavallotti, 2013-01-29 04:09:22

Você pode se referir à Wikipédia , mas a ideia básica da maioria dos padrões de design é introduzir alguma abstração para conseguir uma melhor manutenção e/ou reutilização. O padrão do método de fábrica não é exceção, o que ele faz é abstrair a complexidade da criação do Código.

Para um caso simples parece desnecessário usar o padrão de fábrica, um simples {[[0]} é suficiente. Mas quando você precisa de mais flexibilidade ou funcionalidade, este padrão pode ajudar.

Por exemplo, a menos que uma nova instância seja necessária, a static factory valueOf(boolean) é geralmente uma escolha melhor do que new Bealean(boolean), pois evita a criação de objetos desnecessários. Factory method pattern is also known as Virtual Constructor . Como sabemos, o polimorfismo é uma das principais características da OOP, mas o construtor não pode ser polimórfico, esta lacuna pode ser superada pelo padrão do método de fábrica.

Em essência, instanciar um objecto directamente (normalmente através de new) é apenas um betão. implementação, enquanto método de fábrica padrão de escudos de um volátil implementação por estável interface(não limitado a, interface em Java), empurrando a lógica do objeto-a criação de trás de alguma abstração para garantir mais fácil de manter e de código reutilizável.

Como uma palavra final, para compreender plenamente o benefício do padrão do método de fábrica e de outros padrões de design, é preciso compreender a essência da OOP, incluindo a abstração de dados , abstracção polimórfica e princípio Sólido .

 0
Author: Hui Zheng, 2013-01-29 06:01:53