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