考虑添加静态接口方法以为对象创建提供单个入口点

时间:2017-02-07 07:59:42

标签: java oop java-8 instantiation factory-pattern

“实现”below是否意味着对象的实例?也许它们意味着实施代码。

  

考虑添加静态接口方法,以允许客户端代码   创建(可能是专门的)实现接口的对象。   例如,如果我们有一个带有两个方法的接口Point int x()   和int y(),然后我们可以暴露一个静态方法Point.of(int x,int y)   这会产生一个(隐藏的)接口实现。

     

因此,如果x和y都为零,我们可以返回一个特殊的实现   class PointOrigoImpl(没有x或y字段),否则我们返回   另一个包含给定x和y值的PointImpl类。确保   实现类在另一个包中   显然不是API的一部分(例如,将Point接口放入   com.company。 product.shape和中的实现   com.company.product.internal.shape)。

     

执行此操作:

     

Point point = Point.of(1,2);

     

不要这样做:

     

Point point = new PointImpl(1,2);

这样做的好处是强制执行封装?但是,如果实现是包私有而不是API的一部分,那是否会产生访问问题?如果客户端,“世界”如下:

https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

无法访问Point的实现,那么如何为“执行此操作”实例化新的Point

3 个答案:

答案 0 :(得分:2)

  

例如,如果我们有一个带有两个方法的接口Point int x()   和int y(),然后我们可以暴露一个静态方法Point.of(int x,int y)   这会产生一个(隐藏的)接口实现。

1)请注意,从Java 8开始,您可以在界面中添加静态方法,但在您不能之前。

2)我很难理解这个建议:

  

因此,如果x和y都为零,我们可以返回一个特殊的实现   class PointOrigoImpl(没有x或y字段),否则我们返回   另一个包含给定x和y值的PointImpl类。确保   实现类在另一个包中   显然不是API的一部分(例如,将Point接口放入   com.company。 product.shape和中的实现   com.company.product.internal.shape)。

以下是与您引用的文本匹配的示例Point类:

package com.company.product.shape;

import com.company.product.internal.shape.PointOrigoImpl;
import com.company.product.internal.shape.PointImpl;

public interface Point{
   int x();
   int y();     
   static Point of(int x, int y) {
      if (x == 0 && y == 0){
         return new PointOrigoImpl();
      }
      return new PointImpl(x, y);
  }
}

如果向客户端提供Point接口并且它声明了工厂方法,那么要编译正常,Point接口必须具有PointOrigoImpl和{{1}的可见性为了实例化它们的类。

由于PointImpl接口和子类位于两个不同的包中(Pointcom.company.product.shape), 这意味着com.company.product.internal.shapePointImpl应该有一个公共构造函数,否则PointOrigoImpl无法实例化它们。
最后,操纵Points的客户端也可以实例化PointPointImpl子类的构造函数。

它违背了工厂的目的,该工厂不希望公开实施以选择自己的实施方式返回。

界面是公开的,旨在让客户完全可以访问 因此,作为一般规则,它不应包含我们不希望向客户公开的实现。

3)这里:

  

这样做的好处是强制执行封装?但是,如果   实现是包私有而不是API的一部分,那样做   不创建访问问题?如果客户,"世界"在这里:   无法访问Point的实现,那么它怎么可能   可能会实例化一个新的Point,如上所述"执行此操作"?

我想你想知道为什么文字说:  确保实现类位于另一个明显不属于API 的包中。

在您所引用的文本中,作者希望让PointOrigoImpl客户知道界面,但他不想知道Point的子类,因为他想要决定根据工厂Point中使用的参数返回点子类。

点客户端只会知道此界面。

在Java中,为了不提供对实现类的访问,您可以使用公共类,接口和内部私有类:

  • 公共类向客户端公开,以调用返回实现的工厂方法
  • 所有人都知道接口类,并且没有与实现耦合。
  • 内部私有类构成了公共类的一部分。客户端无法看到它,但工厂看到它返回合适的实现。

根据你提到的例子,它会是直的。

点(界面):

Point

Point factory(包含私有类的公共类):

public interface Point{
   int x();
   int y();            
}

答案 1 :(得分:1)

PointImpl也可以使用公开的API来创建自己,可能是PointImpl.create(int x, int y)PointOrigoImpl.create()的形式。由于它们都在内部包中,因此它们可以是公开的,Point.of可以自由使用它们,而技术上“隐藏”给API的用户,因为它们在com.company.product.internal.shape中残留。

当然,这是善意的,程序员不会滥用PointImpl.create而不是Point.of,但这是正常的。如果程序员想要打破封装(或需要打破封装),那么无论如何都不会阻止他(因为它应该是这样)。

答案 2 :(得分:0)

  

如果客户端“world”无法访问Point的实现,那么它怎么可能像上面那样为“执行此操作”实例化一个新的Point?

客户端不需要实例化,因为实例化发生在<div ui-view ng-controller="SteppersDemoCtrl as vm" layout="column"> ..................................................... ..................................................... <button ng-click="vm.nextStep();">Continue</button> 本身。作为接口Point的实现implements,客户端应该可以访问Point的所有可公开访问的方法,并且客户端可以随时使用这些方法。