如何实现工厂方法模式的灵活性

时间:2012-03-02 06:37:55

标签: java oop design-patterns

我有以下抽象方法模式的例子。

public interface Product {
    public void draw();     
    public void move();
}

public abstract class Creator {     
    public Product anOperation() {
        Product product = factoryMethod();
        return product;
    }

    public abstract Product factoryMethod();
}

public class ConcreateProduct1 implments Product {
    public void draw() {        
    }

    public void move():
    }
}

public class ConcreteCreator1 extends Creator {
    public Product factoryMethod() {
        return new ConcreateProduct1();
    }
}

public class Client {
    public static void main(String arg[]) {
        Creator creator = null;
        creator = new ConcreteCreator1();
        creator.anOperation().move();
    }
}

到目前为止,我已经了解到添加新产品的灵活性是工厂方法模式的主要优势。

有人可以解释一下我们如何实现我们在下面的例子中无法实现的灵活性吗?

public class ConcreateProduct1 {
    public void draw() {        
    }

    public void move():
    }
}

public class Client {
    public static void main(String arg[]) {
        ConcreateProduct1 creator = new ConcreteCreator1();
        creator.move();
    }
}

2 个答案:

答案 0 :(得分:1)

一般来说,工厂在以下情况下很有用:

  • 您需要基于特定条件的不同接口实现
  • 对象的构造很复杂,你不想把它传播到每个地方,而是把它本地化到一个地方。

1的例子:

在您的情况下,客户端代码只会说

Product p = Creator.create(Some_Critera);

在这种情况下,您只需要一个产品。工厂根据标准确定实施方式。

2的例子:

让我们说产品需要注入3种不同的物体。在这种情况下,您所在的每个地方:

new SomeFancyProduct(dep1, dep2, dep3);

您正在重复生成对象的方式。当然,使用IDE,您可以轻松地执行更改方法签名,并在需要更改时完成它。

但是,每当客户需要 SomeFancyProduct 时,每个客户端都需要 dep1 dep2 等。相反,只有 Creator 可以依赖于这3个对象,并且客户端可以是不可知的,因此客户端与 dep1 之间没有任何耦合, dep2 等。

答案 1 :(得分:1)

在你的例子中,它几乎没用。我认为工厂模式永远不会需要:你总是可以用其他方式做同样的事情,但有时候出于某种原因使用起来很方便。例如,它可以用于限制资源使用与私有构造函数的组合 - 它是缓存策略

当与反射代码结合使用时,还有另一个有趣的用法。想象一下,在不知道接口的任何具体实现的情况下编写Factory类。最常见的示例是JDBC API。从客户端代码,您可以通过<driverId>:<params>之类的URL访问数据库。工厂有一个HashMap<String, Class>,因此它可以使用此代码基于<driverId>实例化正确的类型

Class driverClass = drivers.get(driverId);
Constructor constructor = driverClass.getDeclaredConstructor();
return constructor.newInstance(params);

工厂供应商不需要更改实现以添加新的驱动程序,因为它们是dinamically注册和实例化的(在jdbc中这通过Class.forName("com.example.Driver")发生)。请注意,这似乎仍然是一种不必要的复杂性:为什么使用工厂才能获得一个必须知道的课程?在这种情况下,明显的优势是灵活性:驱动程序名称是可以外部化的String(例如在配置文件中)。这样,最终的用户(不是开发人员)可以在不重新编译应用程序的情况下在驱动程序之间切换。