工厂模式动态方法

con*_*ner 14 java design-patterns

我试图了解工厂模式.如果有很多实现,那么我的工厂模式将有很多if else或switch情况.每次我介绍一个新的实现时,我都应该更改我的工厂代码

如下面的例子中如果让代表或切换案例,如果许多动物实现宠物界面我的工厂会如同许多动物实施宠物界面那么假设狗鸭正在实施宠物界面.有没有办法通过带来更多动态方法来解决这个问题?

package com.javapapers.sample.designpattern.factorymethod;

//Factory method pattern implementation that instantiates objects based on logic
public class PetFactory {

    public Pet getPet(String petType) {
        Pet pet = null;

        // based on logic factory instantiates an object
        if ("bark".equals(petType))
            pet = new Dog();
        else if ("quack".equals(petType))
            pet = new Duck();
        return pet;
    }
Run Code Online (Sandbox Code Playgroud)

如果动物长大

if ("bark".equals(petType))
    pet = new Dog();
else if ("quack".equals(petType))
    pet = new Duck();
else if ("mno".equals(petType))
    pet = new MNO();
else if ("jkl".equals(petType))
    pet = new JKL();
else if ("ghi".equals(petType))
    pet = new GHI();
else if ("def".equals(petType))
    pet = new DEF();
......
else if ("abc".equals(petType))
    pet = new ABC();
return pet
Run Code Online (Sandbox Code Playgroud)

Eug*_*kov 23

我认为有一种动态的方法:

  1. 在你的工厂,你需要一个 Map<String, Class<? extends Pet>>
  2. 在扩展Pet的每个类的静态构造函数中,使用这样的map注册它.
  3. 比创建一个类只是map.get(pet).newInstance(你必须检查空值,当然)

  • 但是,有一点需要注意,必须加载类才能执行静态构造函数.如果从未引用过类,则不会自动执行此操作.如果你曾经遇到过一个API,你必须先做一个任意的`Class.forName("")`,这就是对此的一个演示.这不是禁止,这只是值得注意的事情; 某个地方必须加载类. (9认同)

Jas*_*n C 10

工厂模式背后的想法是让您动态实例化在设计时不一定知道的类型的对象.

有一个大块就if打败了这个目的.

实现此模式的有效方法是为每种类型都有一个工厂,它实现了一个基础工厂接口,并且能够实例化该类型的新对象(顺便说一下,在Java中,内置Class是一个例子)这样的工厂).

然后你注册一个名称/ ids /等地图.在运行时对这些单独工厂的实例.当实例化其中一种类型时,您可以按名称在地图中查找工厂,并使用它来实例化该类型的新对象.

你如何在地图上注册个别工厂完全在空中.您可以明确注册一些,您可以扫描配置文件等.

基本上,您希望if使用在运行时动态创建的映射替换块.

您甚至不需要单独使用预先注册的"地图" - 有时可能适合弄清楚如何动态创建具有给定名称的对象,或两者的组合(例如Class.forName(),如果它在类路径中搜索)找不到已加载的类).关键是将名称转换为类类型可以在没有基本工厂实际知道类类型的情况下进行.

值得注意的是,Java反射已经通过Class.forName()和/或提供了非常可行的工厂实现Class.newInstance(),因此如果有意义,请考虑使用它而不是重新发明轮子.

  • 只是为了添加名称,这种模式称为"抽象工厂模式". (4认同)