单身角色在驼鹿

mjn*_*n12 6 perl singleton moose

我正在尝试使用Perl和Moose编写单例角色.我知道MooseX :: Singleton模块是可用的,但是当我们的项目需要另一个CPAN模块时总是存在阻力.在尝试这个并遇到一点麻烦后,我想了解为什么我的方法不起作用.我写的单身人士角色如下:

package Singleton;
use Moose::Role;

my $_singleInstance;

around 'new' => sub {
    my $orig = shift;
    my $class = shift;
    if (not defined $_singleInstance ){
        $_singleInstance = $class->$orig(@_);
    }
    return $_singleInstance;
};

sub getInstance
{
    return __PACKAGE__->new();
}

1;
Run Code Online (Sandbox Code Playgroud)

当只有一个类使用单例角色时,这似乎可以找到.但是,当两个类(例如ClassA和ClassB)都使用Singleton角色时,它们都会引用共享的$ _singleInstance变量.如果我调用ClassA-> getInstance,它将返回对ClassA对象的引用.如果我稍后在同一个脚本中调用ClassB-> getInstance,它将返回对ClassA类型的对象的引用(即使我明确地为ClassB调用了getInstance方法).如果我不使用角色并实际将代码从Singleton角色复制并粘贴到ClassA和ClassB中,它似乎工作正常.这里发生了什么?

Eth*_*her 5

您正在保存所有类型的实例,而不是为每个类类型使用不同的实例。

这需要工厂设计模式,例如:

package MyApp::Factory;

my %instances;

# intantiates an object instance if there is none available,
# otherwise returns an existing one.
sub instance
{
    my ($class, $type, @options) = @_;

    return $instances{$type} if $instances{$type};
    $instances{$type} = $type->new(@options);
}
Run Code Online (Sandbox Code Playgroud)

如果你真的想要单身人士,请安装 MooseX::Singleton 而不是自己滚动 - 如果你查看源代码,你会发现它占了很多边缘情况。但是,我建议不要强制您的类成为单例,因为这会消除类本身的控制。相反,使用工厂(如上所述),这样调用者就可以决定如何构造类,而不是强制所有消费者进入一个用例。