0

如何确保仅通过另一个特定对象实例化一个对象?

例如,假设我有一个 Registry 对象来存储我的 Mappers。当客户端代码调用get()Registry 上的方法时,它会延迟加载并返回请求的 Mapper。这很好,除了没有什么可以阻止客户端代码使用new操作符创建 Mapper 的重复实例。

我能想到的唯一选择是我的 Mappers 需要一个 Registry 对象作为参数。还有其他选择吗?

你做什么工作?我是否应该为防止这种重复而烦恼?

4

3 回答 3

1

也许您不应该试图阻止人们自己创建实例?如果您不相信自己或您的同事不会在不应实例化对象的地方实例化对象,那么您就有问题了。

如果映射器不需要注册表来运行,则不应通过构造函数反对它。将它传递给一些静态方法似乎很奇怪,并且由于您使用的是静态的,因此会使您的代码不太灵活。您将如何对映射器进行单元测试,而无需编写一些技巧来通过注册表正确实例化它们,您在这些测试中不需要?好帖子在这里:http: //kore-nordmann.de/blog/0103_static_considered_harmful.html

于 2012-12-11T08:23:22.317 回答
0

您无法保护new运营商。但是,您可以做的是,您的类中有一个get()方法可以使您的类/对象成为单例(或像您一样使用注册表)。

class clTest {
 private static $oInstance;

 public static function get() {
  if( !self::$oInstance ) {
   self::$oInstance = new clText;
  }

  return self::$oInstance;
 }
}
于 2012-12-11T07:19:44.233 回答
0

如果您希望防止外部实例化,您只需将 __construct 声明为私有,然后使用对静态方法的调用来获取 Mapper 类的实例。然后,您可以传入注册表类的实例,并且仅当参数是注册表类的实例时才返回一个新实例。

class Mapper{
  private __construct(){}

  public static function getInstance($registry){
    if($registry instanceof Registry){
      return new Mapper();
    }
  }
}

$registry = new Registry();
$mapper = Mapper::getInstance($registry);
于 2012-12-11T07:23:53.977 回答