new
建造建造者。你需要一些其他方法來實際返回構建的對象。
下面是一個例子:
class RepositoryBuilder {
has 'allow_network_repositories' => (
is => 'ro',
isa => 'Bool',
required => 1,
);
method build_repository(Uri $url) {
confess 'network access is not allowed'
if $url->is_network_url && !$self->allow_network_repositories;
my $class = $self->determine_class_for($url); # Repository::Whatever
return $class->new(url => $url);
}
}
role Repository { <whatever }
class Repository::File with Repository {}
class Repository::HTTP with Repository {}
這裏,建設者和內置的對象是不同的。該構建器是一個真實對象,帶有參數,可根據具體情況進行自定義以構建 對象。然後,「構建」的對象是 只是返回一個方法的值。這使您可以根據具體情況構建其他 構建器。 (構建器 函數的一個問題是它們非常不靈活 - 很難教它們 一個新的特例。構建器對象 仍存在此問題,但至少您的應用程序可以創建子類,實例化它, 而這個對象傳遞給任何需要創建對象,但 依賴注入是在這種情況下,更好的方法。)
而且,也沒有必要爲您打造從 任何繼承庫,他們只需要一個標記表明它們是存儲庫。 這就是我們的Repository
角色所做的。 (您會希望在此添加 API代碼以及任何應該重用的方法。但要小心 關於強制重用 - 你確定所有用 存儲庫角色標記的東西都需要這樣的代碼嗎?如果沒有,只需將代碼放入 中,然後將其應用於需要 功能的類。)
以下是我們如何使用我們創建的構建器。比如說,如果你不想 觸控網絡:
my $b = RepositoryBuilder->new(allow_network_repositories => 0);
$b->build_repository('http://google.com/'); # error
$b->build_repository('file:///home/whatever'); # returns a Repository::Foo
但是,如果你這樣做:
my $b = RepositoryBuilder->new(allow_network_repositories => 1);
$b->build_repository('http://google.com/'); # Repository::HTTP
現在你有一個建立的對象,你喜歡的方式建設者, 你只需要在其他代碼中使用這些對象。因此,拼圖中的最後一塊 指代其他 代碼中的「任何」類型的Repository對象。這很簡單,你用does
代替isa
:
class SomethingThatHasARepository {
has 'repository' => (
is => 'ro',
does => 'Repository',
required => 1,
);
}
大功告成。
mmh ...讓我明白這個角色的事情,回到穆斯文檔... 另外,我首先想到它,因爲我剛開始與穆斯,是否繼續做不好的駝鹿不是駝鹿 – 2010-06-08 11:18:09
@alex:如果你按照Moose :: Manual :: *中的例子,你可以使用駝鹿的大部分特徵而不會遇到困難。只有當你開始使用'meta'時,事情纔會變得瘋狂:) – Ether 2010-06-08 16:04:33
ok,理解,但我很好奇這些細微的差異: a)一個包含所有基本屬性的Moose基類「Repository」專門的Moose類'Repository :: _Sftp'表示「擴展」/繼承基類;一個駝鹿(或不)工廠'RepositoryBuilder',用一種方法爲我創建一個專門類的實例,它可以作爲'Repository'被無意識地操縱。 b)和a)一樣,但是用一個角色代替基類< - 這就是你的建議,對吧? c)和d)MooseX :: AbstractFactory或MooseX :: ABC,但這些默認情況下不可用(我把centos5作爲ref) – 2010-06-09 04:26:23