Java 春迪,工厂服务

Java 春迪,工厂服务,java,spring,factory-pattern,Java,Spring,Factory Pattern,这更多的是一个设计问题,而不是代码实现,但我希望有人能帮上忙 我面临的问题是,我需要根据两个输入注入modelSerivce。基于一些文档和问题,我非常确定我想使用factorybean来实现这一点 我的问题更多地涉及这些类的构造,这些类将使用factorybean创建。如何在工厂中重复使用单例bean,而不是每次调用工厂时都创建一个新类 下面是代码的样子: 事物接口: public interface Thing { void Run(); } ThingA实施: public cl

这更多的是一个设计问题,而不是代码实现,但我希望有人能帮上忙

我面临的问题是,我需要根据两个输入注入modelSerivce。基于一些文档和问题,我非常确定我想使用factorybean来实现这一点

我的问题更多地涉及这些类的构造,这些类将使用factorybean创建。如何在工厂中重复使用单例bean,而不是每次调用工厂时都创建一个新类

下面是代码的样子:

事物接口:

public interface Thing {
    void Run();
}
ThingA实施:

public class ThingA implements Thing{
    public void Run() {
        System.out.println("In ThingA");
    }
}
public class ThingB implements Thing{
    public void Run() {
        System.out.println("In ThingB");
    }
}
public class ThingFactory {
    public Thing GetThing(String stateCode, Date date){
        Thing result;
        if(stateCode == "MA") {
            result = new ThingA();
        }
        else {
            result = new ThingB();
        }
        return result;
    }
}
ThingB实现:

public class ThingA implements Thing{
    public void Run() {
        System.out.println("In ThingA");
    }
}
public class ThingB implements Thing{
    public void Run() {
        System.out.println("In ThingB");
    }
}
public class ThingFactory {
    public Thing GetThing(String stateCode, Date date){
        Thing result;
        if(stateCode == "MA") {
            result = new ThingA();
        }
        else {
            result = new ThingB();
        }
        return result;
    }
}
ThingFactory实施:

public class ThingA implements Thing{
    public void Run() {
        System.out.println("In ThingA");
    }
}
public class ThingB implements Thing{
    public void Run() {
        System.out.println("In ThingB");
    }
}
public class ThingFactory {
    public Thing GetThing(String stateCode, Date date){
        Thing result;
        if(stateCode == "MA") {
            result = new ThingA();
        }
        else {
            result = new ThingB();
        }
        return result;
    }
}
我真正希望工厂做的是拉取一个已知的实现,而不是每次调用工厂时都创建一个实现。我也不想通过这样做将我的工厂与Spring框架捆绑在一起:

ApplicationContext.getBean()
    public class ThingFactory {
        private static Map<String, Thing> instancesMap = new Hashmap<>()
        public static Thing getThing(String name) {
          return instancesMap.get(name);
        }      
    public static addInstance(String name, Thing thing) {
      instancesMap.put(name, thing);
    }

只需像平常一样将bean保持在spring上下文中。将上下文注入工厂,并根据业务规则从工厂中提取bean

public class ThingFactory {

    @Autowired 
    private ApplicationContext ctx;

    public Thing GetThing(String stateCode, Date date){
        Thing result;
        if(stateCode == "MA") {
            result = ctx.getBean("someBean")
        }
        else {
            result = ctx.getBean("someOtherBean")
        }
        return result;
    }
}
您甚至可以更聪明地使用方案在上下文中命名bean:

@Service("Thing_MA")
public class ThingA implements Thing{
.
.
.
}
这为您的工厂提供了很好的声明性查找规则:

public class ThingFactory {
    public Thing GetThing(String stateCode, Date date){
        return (Thing) ctx.getBean("Thing_" + stateCode);

   }
}

事实上,我处理过同样的问题,这是我提出的解决方案。我所依赖的主要技巧是,任何定义为singletone的bean在Spring初始化时都由Spring实例化。以下是我所做的:

  • 在您的例子中,添加一个抽象类
    ThingImpl
    ,它实现了您的
    东西
    接口,并将成为所有
    ThnigA
    ThingB
    。。。上课。(或者只需将
    对象
    接口更改为抽象类)
  • 将您的
    ThingFactory
    更改为如下内容:

    ApplicationContext.getBean()
    
        public class ThingFactory {
            private static Map<String, Thing> instancesMap = new Hashmap<>()
            public static Thing getThing(String name) {
              return instancesMap.get(name);
            }      
        public static addInstance(String name, Thing thing) {
          instancesMap.put(name, thing);
        }
    

    如果您不想绑定您的code spring框架,这意味着您不想
    BeanFactory
    并创建自己的工厂,那么您必须自己创建对象

    public class ThingFactory {
    
        private final static Thing thingA = new ThingA();
        private final static Thing thingB = new ThingB();
    
        public Thing GetThing(String stateCode, Date date){
            if(stateCode.equals("MA")) {
                return thingA;
            } else {
                return thingB;
            }
        }
    }
    
    如果你有更多的
    东西的实现,在这种情况下,你只需创建一个映射,并根据需要获取对象

    public class ThingFactory {
    
        private final static Map<String, Thing> beanMap = new Hashmap<>()
    
        public ThingFactory(){
            addThing("ThingA", new ThingA());
            addThing("ThingB", new ThingB());
        }
    
        public static Thing getThing(String name) {
          return beanMap.get(name);
        }      
    
        public static addThing(String name, Thing thing) {
           beanMap.put(name, thing);
        }
    
        public Thing GetThing(String stateCode, Date date){
            if(stateCode.equals("MA")) {
                return getThing("ThingA");
            } else {
                return getThing("ThingB");
            }
        }
    }
    

    什么时候才能知道这些输入?这是一个非常模糊的描述。请添加一些代码片段,以便清楚地理解。您可以通过Robert的factory使用Singleton,将上下文注入到代码中会使您的代码Spring意识到这是一个缺点。请参阅我的答案,了解如何在不使用contextSure的情况下执行相同的操作。我想如果我使用spring,我宁愿依赖spring,也不愿让我的所有东西都了解工厂。在我看来,你只是在复制春天的背景。但你的方式是有效的,我会试着让你按照我的方式走。事实上,我的方式违背了弹簧所带来的非强制性原则。请参见此处:。然而,我也不得不说,您的解决方案同样有效。我坚信我的更好:)我们必须同意不同意。我认为您正在创建一个不必要的类层次结构。我完全可以想象,想要在不参考工厂的情况下实例化您的东西的POJO,因此它看起来已经像是一种糟糕的代码味道!您的核心业务类或多或少带有任意的实现/生命周期问题。在我的方法中,只有工厂依赖于spring,这似乎是显而易见的。您可以将final添加到这两个参数中吗?