Как вы «лениво загружаете» пакеты, используемые в качестве делегатов? - PullRequest
2 голосов
/ 10 ноября 2011

Есть ли способ, которым я могу динамически включать пакет на основе того, какой делегат используется, вместо того, чтобы включать все различные делегаты?

Я нашел этот пример о том, как использовать делегатов, но он закрывает детали, которые я пытаюсь понять.Как это написано, это по сути всего один файл ...

package Compare;
use Moose::Role;
requires 'compare';


package SpaceshipCompare;
use Moose;
with 'Compare';  

sub compare { my ($a, $b) = @_; return $a <=> $b }

package Sort;
use Moose;

has 'comparer' => (
    is       => 'ro',
    does     => 'Compare',
    handles  => 'Compare',
    required => 1,
);

sub my_sort {
    my ($self, @list) = @_;
    return sort { $self->compare($a, $b) } @list;
}

Использование:

my $sorter = Sort->new( comparer => SpaceshipCompare->new );
my @sorted = $sorter->my_sort("1one", "0", "43");

В моей реализации делегата я использую другой ресурс, основанный на параметреэто передается конструктору.

  sub BUILD{
    my($this,$args) = @_;

        if($args->{cachedDataSource} eq 'local'){

            $this->setDataStore( Cache::LocalCache->new() ); 

        }

        if($args->{cachedDataSource} eq 'remote'){

            $this->setDataStore( Cache::RemoteCache->new() ); 

        }


        if($args->{cachedDataSource} eq 'memd'){

            $this->setDataStore( Cache::MemedCache->new() ); 

        }

}

Но для того, чтобы это работало, мне нужно

use Cache::LocalCache;
use Cache::RemoteCache;
use Cache::MemedCache;

Есть ли лучший способ сделать делегатов без использования всех пакетов?(вроде какой-то ленивой нагрузки)?

1 Ответ

5 голосов
/ 10 ноября 2011

В вашем примере вы можете просто использовать require :

sub BUILD{
    my($this,$args) = @_;

        if($args->{cachedDataSource} eq 'local'){
            require Cache::LocalCache;
            $this->setDataStore( Cache::LocalCache->new() ); 
        }

        if($args->{cachedDataSource} eq 'remote'){
            require Cache::RemoteCache;
            $this->setDataStore( Cache::RemoteCache->new() ); 
        }

        if($args->{cachedDataSource} eq 'memd'){
            require Cache::MemedCache;
            $this->setDataStore( Cache::MemedCache->new() ); 
        }
}

Поскольку require является операцией во время выполнения, класс не будет загружен, пока он действительно не понадобится. Если ваши пользователи передавали имена классов, это становится немного сложнее. Вы можете использовать Module :: Load для этого.

...