工厂模式示例 - 需要解决以下代码

时间:2012-09-12 15:48:37

标签: java design-patterns

package com.factory;

import java.util.HashMap;
import java.util.Map;

//Factory class
class FactoryClass {
        Map products = new HashMap();

        void registerProduct(String prodId, ProductInt prodInterface) {
            products.put(prodId, prodInterface);
        }

        ProductInt createProduct(String prodId) {
            return ((ProductInt) products.get(prodId)).createProduct();
        }
}    

// Client
public class FactoryPattern {
    public static void main(String[] args) {
        FactoryClass factory = new FactoryClass();
        factory.createProduct("pen");
    }
}

package com.factory;

//Interface Product
public interface ProductInt {
    ProductInt createProduct();
}

// Concrete Product-1
class Pen implements ProductInt {
    static {
        FactoryClass factory = new FactoryClass();
        factory.registerProduct("pen", new Pen());
    }

    public ProductInt createProduct() {
        return new Pen();
    }
}

// Concrete Product-2
class Pencil implements ProductInt {
    static {
        FactoryClass factory = new FactoryClass();
        factory.registerProduct("pencil", new Pencil());
    }
    public ProductInt createProduct() {
        return new Pencil();
    }

}

当我运行此代码时,我得到nullpointer,因为没有在hashmap中注册产品。所以,当我为“铅笔”请求一个Product实例时,它找不到任何键来返回具体的Pencil类object.can任何一个帮我编码 - 就像在Factory和具体类之间不应该有任何关系,这样注册将保留在Factory类之外,我应该得到我要求的适当的具体类对象?

由于 巴拉吉

3 个答案:

答案 0 :(得分:0)

您正在创建FactoryClass的单独实例 - 其中每个实例都有自己的Map products实例 - 您在main()方法中创建的工厂与工厂不同您创建并注册了penpencil。显然,FactoryClass.products中没有注册任何项目。

一种方法是将Map products中的FactoryClass声明为static - 这将解决您的直接问题 - 尽管整体而言您的代码似乎需要其他改进在其他地方。

答案 1 :(得分:0)

夫妻问题:

首先,工厂方法应该是static或与正在创建的类不同的类。因此,拥有interface的唯一方法是创建接口的实例并不合乎逻辑。您可能会遇到InterfaceA创建InterfaceB实例或接口为通用FactoryInterface<X>的情况并创建X实例的情况。请参阅Guava的Supplier界面

例如,Pen ...除非您已经拥有Pen.createProduct()的实例,否则无法调用Pen,因为该方法不是静态的。

因此,考虑到上述情况,请考虑让Factory采用Producer<X>Supplier<X>来创建X的实例。

其次,考虑让您的工厂类成为Singleton。您遇到的问题是每个静态初始化都会创建一个立即丢弃的新工厂实例。因此,当您稍后尝试获取映射值时,您将从与其注册的实例不同的实例获取它。

最后,在以某种方式使用/触摸类之前,不调用类的静态初始化器。您需要在PenPencil上调用某些内容来调用它们的静态初始化程序块,从而自行注册。

答案 2 :(得分:0)

除上述答案外,http://www.oodesign.com/factory-pattern.html说: 我们必须确保在工厂要求注册之前加载具体的产品类(如果它们未加载,它们将不会在工厂中注册,createProduct将返回null)。为了确保它,我们将在主类的静态部分中使用Class.forName方法。

class Main {

static
{
    try
    {
        Class.forName("OneProduct");
        Class.forName("AnotherProduct");
    }
    catch (ClassNotFoundException any)
    {
        any.printStackTrace();
    }
}
public static void main(String args[]) throws PhoneCallNotRegisteredException
{
    ...
}
}