我正在寻找以下模式。 (我正在使用Perl,但我认为语言并不重要)。如何创建派生类由创建属性隐式指定的对象?
与父母班Foo,和儿童酒吧,巴兹,Bazza。
构建Foo的方法之一是解析一个字符串,并且该字符串的一部分将隐式指定要创建哪个类。例如,如果它启动'http:',那么它是一个Bar,但如果它不包含'[Date]',那么Baz喜欢它,等等。
现在,如果Foo知道它的所有孩子,以及什么字符串是一个Bar,什么是Baz等,它可以调用适当的构造函数。但是基础班不应该有任何关于其子女的知识。
我想要的是Foo的构造函数能够依次尝试它的孩子,直到其中一个人说:“是的,这是我的,我会创造出这个东西”。
我知道,在一般情况下,这个问题没有明确定义,因为可能有多个孩子接受这个字符串,所以他们被称为重要的顺序:忽略这个,并假设字符串的特征是只有一个子类会喜欢字符串。
我想出的最好的方法是让子类在初始化时对基类进行“注册”,以便它获取构造函数列表,然后遍历它们。但有没有更好的方法,我错过了?
示例代码:
package Foo;
my @children;
sub _registerChild
{
push @children, shift();
}
sub newFromString
{
my $string = shift;
foreach (@children) {
my $object = $_->newFromString(@_) and return $object;
}
return undef;
}
package Bar;
our @ISA = ('Foo');
Foo::_registerChild(__PACKAGE__);
sub newFromString
{
my $string = shift;
if ($string =~ /^http:/i) {
return bless(...);
}
return undef;
}
谢谢。逻辑模块:: Pluggable非常好,正是我所期待的;但它可能不适合我们的情况,因为它可能不会出现在我们用户的机器上,所以我们必须使用我们自己的模块进行分发。 与我的注册解决方案相比,这也是“神奇的”,所以它可能不太清楚。 但是,感谢您的关注。 – 2009-06-16 14:27:48
这是有点神奇,但默认行为只会加载MyClass :: Plugin命名空间中的类(并且该命名空间很容易覆盖)。因此,注册与在该名称空间中创建模块的效果完全相同。 很显然,它是一个CPAN模块,但如果您现在可以在没有CPAN(或大量的车轮重新创建)的情况下管理Perl中的任何严重应用程序,我会感到惊讶。 – 2009-06-16 15:06:05