Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java对象创建模式与设计_Java_Object_Factory - Fatal编程技术网

Java对象创建模式与设计

Java对象创建模式与设计,java,object,factory,Java,Object,Factory,我最近开始从事一个Java项目,该项目已经有一个相当大的代码库,由一个团队在3个月内开发。我注意到,在许多地方,一些对象直接在客户机对象的构造函数中实例化,而不是使用依赖项注入。我想把对象结构重构成一个工厂,并使用一些注入框架 我创建了一个工厂,它本质上是一个doingnew的一行程序。这里没有什么花哨的东西——没有单件,没有静态工厂模式。只有一个newInstance()方法,它返回依赖项的新实例 要在代码中显示某些内容: class A { A() { B bobj =

我最近开始从事一个Java项目,该项目已经有一个相当大的代码库,由一个团队在3个月内开发。我注意到,在许多地方,一些对象直接在客户机对象的构造函数中实例化,而不是使用依赖项注入。我想把对象结构重构成一个工厂,并使用一些注入框架

我创建了一个工厂,它本质上是一个doing
new
的一行程序。这里没有什么花哨的东西——没有单件,没有静态工厂模式。只有一个
newInstance()
方法,它返回依赖项的新实例

要在代码中显示某些内容:

class A {   A() {  
       B bobj = new B();  // A and B are coupled directly
    } 
}
我想将其重构为:

BFactory {
    newInstance() {  return new B(); // return B implementation  }
}

 class A {
   A(BFactory factory){  
     B bobj = factory.newInstance(); // A does not know about B impl
  }
}
我的论点是,不应该在代码中的任何地方创建对象,除非是在用于此目的的工厂中。这会促进松散耦合,否则会将这两种类型紧密耦合。一位资深成员(我试图重构的代码的作者)认为单行程序工厂的设计过于复杂

是否有权威性的建议/参考来解决这个问题?可以用来决定哪种方法更好,为什么更好

一位资深成员(我试图重构的代码的作者)认为单行程序工厂的设计过于复杂

这似乎是您问题的关键,而不是您是否应该重构代码。因此,让我们回答它,而不是偏离实际问题。如果我们考虑你在代码中出现的例子,我同意你的同事。您不应该为每个要注入的依赖项创建工厂类。你试图实现的目标没有错,但是你试图实现它的方式是一种过度的杀伤力

您要么依赖于知道如何创建每个依赖项的
工厂
类的层次结构,要么依赖于实际的类本身,拥有一个
容器
,可以将对象连接在一起

选项1:依赖于一个通用工厂

class A {
   B bobj;
   C cobj;
   A(Factory factory){  
     bobj = factory.createB(); 
     cobj = factory.createC();
   }
}
class A {
   B bobj;
   C cobj;
   A(A a,B b) {  
      this.bobj = b;
      this.cobj = c
   }
}
选项2:直接依赖依赖依赖关系

class A {
   B bobj;
   C cobj;
   A(Factory factory){  
     bobj = factory.createB(); 
     cobj = factory.createC();
   }
}
class A {
   B bobj;
   C cobj;
   A(A a,B b) {  
      this.bobj = b;
      this.cobj = c
   }
}
然后可以创建一个
容器
类,该类知道如何将对象连接在一起:

class Container {
    public static B createB() {
        return new BImpl();
    }

    public static C createC() {
         return new CImpl();
    }

    public static A createA() {
        return newAImpl(createB(),createC());
    }
}

上面的例子太基本了。在现实世界中,大多数情况下都会有更复杂的依赖关系图。这就是DI框架派上用场的地方,而不是重新发明轮子。如果您的最终目标是开始使用DI框架,那么您可以选择选项2,因为DI框架通过向其客户机提供依赖项而不是客户机代码来实现控制反转。

您的基本点是完全有效的,直接在构造函数中实例化对象通常不是一个好主意(它们可能是该规则的有效例外)

如果您这样做:

class Car {

   private Engine engine;

   public Car() {
       engine = new Engine();
   }

}
在没有引擎的情况下,你将很难测试汽车。你必须使用反射来通过模拟来交换实例

如果您改为执行以下操作

class Car {

   private Engine engine;

   @Inject
   public Car(Engine engine) {
       this.engine = engine;
   }

}
使用假发动机测试汽车、更换发动机的实现或改变发动机的构造方式(例如,向构造器添加更多参数)非常容易

但是你绝对应该使用一个已经建立的依赖注入框架,而不是编写你自己的工厂。如果你像Chetan建议的那样传入一个“公共工厂”,你最终会隐藏你的依赖

在这里可以找到使用依赖项注入获得更多动力的好资源: 或
(非常好的谈话,应该值得你花时间)。

我的论点是“如果它没有损坏,就不要修复它。”使用工厂方法获得的耦合损失不值得花时间或冒风险(bug)它需要触及你代码库的每一部分。现在就开始吧。你的帖子能举一个简短的例子来说明你在说什么吗?你的描述可以用几种不同的方式来解释。我会稍微将@markspace的注释改为“等到它坏了再修复它”。如果您需要使用工厂方法进行更简单、更干净的更改,请重构该类的构造。如果某个类正在运行且不需要更改,请别管它。我认为这个问题不值得以主要基于意见的方式来结束。OP问他做某事的方式是否正确正确的方法。我不认为答案取决于你的情况。只有在你需要的时候才使用松耦合,如果一个工厂可以创建该接口/类的多个实现,那么你应该使用一个工厂来创建它们,如果它是一个对象,那么不要通过向它添加工厂来让生活变得复杂。为什么不同时使用这两种类型的构造函数呢从这两个类中,一个是提供引擎的默认类,而另一个则允许您注入引擎。@AlexC以及当其中一个客户端的
DefaultEngine
不再是以前的
DefaultEngine
时会发生什么?理想情况下,
工厂
应该注入一个作为默认引擎的引擎f客户不知道他们想要什么引擎。对于一个客户,
Engine1
可能是默认引擎,而对于另一个客户,
Engine2
应该是
Car
真的在乎吗?答案是否定的,因为这违背了控制反转的目的。很多假设。你编了一个用例,现在正在编约束ts和回答您自己的问题。如果包含默认值的IoC配置不再是以前的配置,该怎么办?代码可能会过时,配置文件也可能会过时。请再次阅读我的答案,您可以同时拥有默认行为和IoC,您的重点是什么?@AlexC我认为您完全没有理解我的意思。让我重新措辞。默认引擎有什么不同t来自任何其他
发动机
。为什么
汽车
应该知道它的默认发动机是什么?汽车不应该是汽车