更新
现在有一个很多更好的方法来做到这一点,使用MooseX::ClassAttribute
然后只需使用class_has 而不是has 来作为您希望与所有实例共享的方法。
package My::Class;
use Moose;
use MooseX::ClassAttribute;
class_has 'Cache' =>
( is => 'rw',
isa => 'HashRef',
default => sub { {} },
);
__PACKAGE__->meta()->make_immutable();
旧
此外,是否有描述这种行为的设计模式?
是的。它被称为单例。单例模式是一种模式,多个启动(调用->new)将返回相同的对象。您可以这样做,也可以将变量存储在类之外。 Moose 提供了一个允许您轻松创建单例的层(认为这两种方法都不是特别难):模块MooseX::Singleton。 Moose 还允许您delegate to another object by using an accessor。
这里我们使用MooseX::Singleton,并委托一个隐藏的属性来达到预期的效果。
package MySingleton;
use MooseX::Singleton;
has 'foo' => ( is => 'rw', isa => 'Bool', default => 0 );
package ClassA;
use Moose;
has '_my_singleton' => (
isa => 'MySingleton'
, is => 'ro'
, default => sub { MySingleton->new }
, handles => [qw( foo )]
);
package ClassB;
use Moose;
has '_my_singleton' => (
isa => 'MySingleton'
, is => 'ro'
, default => sub { MySingleton->new }
, handles => [qw( foo )]
);
package main;
use Test::More tests => 5;
my $class_a = ClassA->new;
my $class_b = ClassA->new;
is( $class_a->foo(0), 0, 'Set A to false' );
is( $class_a->foo, 0, 'A Is false' );
is( $class_b->foo, 0, 'B Is false' );
is( $class_b->foo(1), 1, 'Set B to true' );
is( $class_a->foo, 1, 'A is true' );
或者,没有 MooseX
除非需要,否则请不要这样做。 MooseX 方法要好得多:
package Underclass;
use Moose;
has 'foo' => ( is => 'rw', isa => 'Bool', default => 0 );
package SingletonWrapper;
my $obj;
sub new {
if ( $obj ) { return $obj; }
else { $obj = Underclass->new }
}
package ClassA;
use Moose;
has '_my_singleton' => (
isa => 'Underclass'
, is => 'ro'
, default => sub { SingletonWrapper->new }
, handles => [qw( foo )]
);
package ClassB;
use Moose;
has '_my_singleton' => (
isa => 'Underclass'
, is => 'ro'
, default => sub { SingletonWrapper->new }
, handles => [qw( foo )]
);