perl - 在作为另一个对象的访问者的对象列表中搜索

时间:2016-10-17 12:48:14

标签: perl oop moose

我是Perl-OO初学者,我遇到了设计挑战。我希望你能给我一些提示,以获得一个优雅的解决方案。我在这里使用鼠标对象系统。

对于一个最小的例子,我想说我有一个用户对象。用户有一个名字。

package User;
use Mouse;    

has "name" => (
   is        => "rw",
   isa       => "Str|Undef",
);  

然后我有一个User-Cache-Object,它获取所有用户的列表(来自LDAP服务器)。您可以说这是用户缓存和用户之间的“有一个”关系。

package UserCache;
use Mouse;    

has "users" => (
   is        => 'rw',
   isa       => 'ArrayRef|Undef',
   default   => sub { [] },
);  

我将此用户列表存储为用户缓存的访问者中的用户对象数组。

 my $cache = UserCache->new();

 foreach my $entry ( $ldap->searchGetEntries() ) { 
      my $user = User->new();
      $user->name($entry->get_value('userdn'));
      push @{ $cache->users }, $user;
 }

现在这就是我的问题所在。如果我想找到具有特定属性的用户对象(例如名为John的用户),我必须遍历整个用户对象数组并查询每个对象名称。当给出一个名单列表时,这会得到一个非常低效的过程。

foreach my $user ( @{ $cache->users } ) {
      if ( $user->name eq 'John' ) {
           #do something with John
      }...
} 

有没有办法以某种方式存储对象列表在其他对象中,我可以有效地搜索?喜欢 $ cache-> get_users-> get_name('John')并返回我需要的对象?

2 个答案:

答案 0 :(得分:5)

你真的不必自己写UserCache课程。而是使用CHI缓存要在要用于查找的密钥下缓存的用户。如果需要,可以将缓存类包装为从特定缓存实现中抽象出来。

另外,你有这个:

push @{ $cache->users }, $user;

泄漏实施细节的地方。相反,您的UserCache对象需要类似save_user方法的内容,因此它使用的代码不依赖于实现细节。

$cache->save_user( $user );

对于Moose物体,你得到Moose::Meta::Attribute::Native::Trait::Array;对于鼠标,您获得MouseX::NativeTraits::ArrayRef

答案 1 :(得分:4)

即可。至少不是普遍的。您当然可以为常见事物构建索引。或者你可以在完成搜索后缓存搜索。

查找最好实现为哈希。这些可以附加到UserCache对象。类似的东西:

my @users = $cache->find( name => 'John' );

这将在内部映射到带有搜索字段的hashref。

package UserCache;
#...

has _search_index => (
    is  => 'ro',
    isa => 'HashRef',
    default => sub { {} },
);

哈希引用看起来像这样:

{
    name => {
        John => [
            User->new( name => 'John', last_name => 'Smith' ),
            User->new( name => 'John', last_name => 'Wayne' ),
            User->new( name => 'John', last_name => 'Bon Jovi' ),
        ],
        James => [ ... ],
    },
    id => {
        # ...
    },
),

但同样,你必须建立那些。所以你需要进行一次查找。但我认为查找应该在UserCache中完成并存储在那里。

sub find {
    my ($self, $key, $value) = @_;

    # get operation
    return @{ $self->_search_index->{$key}->{$value} } 
        if exists $self->_search_index->{$key}->{$value};

    # set operation
    foreach my $user ( @{ $self->users } ) {
        push @{ $self->_search_index->{$key}->{$value} }, $user
            if $user->$key eq $value
    }
    return @{ $self->_search_index->{$key}->{$value} } 
}

这是一个非常天真的实现,它不支持多次查找,但它是一个开始。

请注意,如果您拥有大量用户和大量索引,则数据结构可能会变大。

为方便起见,Moose's built-in traits可能会有所帮助。如果您想要更强的缓存行为,请查看CHI