Можно ли получить существующие объекты лося, а не создать новый, если указаны те же обязательные атрибуты? - PullRequest
3 голосов
/ 27 ноября 2009

Предположим, у меня есть следующий пакет Moose:

package GSM::Cell;
use Moose;

has 'ID' => (is => 'ro', required => 1);
has [qw(BCCH NEIGHBOUR)] => (is => 'rw', default => undef);

no Moose;
__PACKAGE__->meta->make_immutable; 
1;

Затем я создаю два объекта и добавляю один в качестве атрибута 'NEIGHBOR' другого:

my $a = GSM::Cell->new(ID => 20021, BCCH => 1);
my $b = GSM::Cell->new(ID => 20022, BCCH => 2);
$a->NEIGHBOUR($b);

Где-то еще, например в другой процедуре атрибут BCCH $ b может быть обновлен до другого значения:

$b->BCCH(3);

Теперь, если я ссылаюсь на

 $a->NEIGHBOUR->BCCH

тогда я все равно вернусь к исходному значению атрибута BCCH вместо обновленного значения.

Полагаю, разумно было бы добавить ссылку на $ b вместо самого $ b, что решило бы проблему:

$a->NEIGHBOUR(\$b);

Тем не менее, у меня есть сценарий в веб-приложении, где объект, эквивалентный $ b (тот же идентификатор), создается во множестве методов, и изменения могут быть сделаны в любом из них, что затрудняет передачу ссылок на все ваши созданные объекты.

В идеале при звонке на

my $somevar = GSM::Cell->new(ID => 20022);

, объект должен создаваться только в том случае, если объект с таким же идентификатором еще не существует.

Является ли словарь подходящим вариантом, как-то так:

$id = 20022;
my $somevar = $already_created{$id} || GSM::Cell->new(ID => $id);

или есть более аккуратные решения?

Ответы [ 3 ]

3 голосов
/ 27 ноября 2009

Звучит как-то MooseX :: NaturalKey предназначен для.

package GSM::Cell;
use MooseX::NaturalKey;

has 'ID' => (is => 'ro', required => 1);
has [qw(BCCH NEIGHBOUR)] => (is => 'rw', default => undef);

primary_key => ('ID');
no Moose;
__PACKAGE__->meta->make_immutable; 
1;

Потом позже:

my $a = GSM::Cell->new(ID => 20021, BCCH => 1);
my $b = GSM::Cell->new(ID => 20022, BCCH => 2);
$a->NEIGHBOUR($b);
$b->BCCH(3);
say $a->NEIGHBOR->BCCH; # prints 3

my $c = GSM::Cell->new(ID => 20022);
$c->BCCH(4);
say $a->NEIGHBOR->BCCH; # prints 4
2 голосов
/ 27 ноября 2009
  • Разве отношения соседей между двумя ячейками сами по себе не являются объектом, на который должны ссылаться ячейки 20021 и 20022? Изменение значения BCC в одной ячейке может быть затем передано объекту отношений, обновляя обе ячейки.

  • то, что вам нужно сделать, это сохранить ссылки на объекты для ваших ячеек в хеше, скажем, $ Network, и управлять созданием ячейки через фабричный класс, который знает, как проверить хеш $ Network для существующих ячеек ...

1 голос
/ 27 ноября 2009

Я думаю, что проблема, описанная в первой половине вашего поста, не является проблемой.

Если я запускаю ваш код:

package GSM::Cell;
use Moose;

has 'ID' => (is => 'ro', required => 1);
has [qw(BCCH NEIGHBOUR)] => (is => 'rw', default => undef);

no Moose;
__PACKAGE__->meta->make_immutable; 
1;

package main;

my $a = GSM::Cell->new(ID => 20021, BCCH => 1);
my $b = GSM::Cell->new(ID => 20022, BCCH => 2);
$a->NEIGHBOUR($b);

$b->BCCH(3);
print $a->NEIGHBOUR->BCCH, "\n";  # 3

Он печатает обновленное значение, а не старое значение. Это работает, потому что $b является объектом, а все объекты Perl являются благословенными ссылками. Когда вы запускаете $a->NEIGHBOUR($b), вы уже передаете ссылку; нет необходимости передавать ссылку на ссылку.

...