Ищу образец для следующего. (Я работаю на Perl, но не думаю, что язык особенно важен).

С родительским классом Foo и дочерними Bar, Baz, Bazza.

Один из методов создания Foo - это синтаксический анализ строки, и часть этой строки неявно указывает, какой класс должен быть создан. Так, например, если он начинается с «http:», то это Bar, но если его нет, но он содержит «[Date]», то это нравится Базу, и так далее.

Теперь, если 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;
}
3
Colin Fine 16 Июн 2009 в 14:28

4 ответа

Лучший ответ

Если вы воспользуетесь своим комментарием о родительском классе, не содержащем информации о детях и вашем методе делегирования задачи установления соответствия дочерних классов самому классу, то, вероятно, будет правильным вынести выбор класса из родительского класса и создать singleton для этой задачи.

По крайней мере, это было бы моим предпочтением ... из этого ваш текущий родительский класс (который, по-видимому, имеет некоторые общие функции для ваших дочерних классов), по-видимому, затем может стать либо абстрактным, либо интерфейсом.

Затем синглтон может управлять построением всех дочерних классов и их распределением (клонировать их, если они не работают?) ... более того, дочерние классы могут быть перемещены в отдельную dll для содействия разделению.

Извините, это не прямое решение. Я делал это в прошлом, управляя списком классов в синглтоне, как вы здесь. Идея синглтона заключается в том, что если вы действительно хотите использовать какое-либо дорогостоящее отражение, вам нужно сделать это только один раз.

0
John Nicholas 16 Июн 2009 в 12:26

Вы можете реализовать произвольный алгоритм поиска в классе Foo, который ищет существующие дочерние классы. Возможно, на основе файлов конфигурации, предоставленных дочерними классами, или с помощью любого другого механизма, о котором вы можете подумать.

Затем класс Foo обнаружит существующие клиентские классы во время выполнения и вызовет их по очереди.

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

0
mkoeller 16 Июн 2009 в 11:31

Кажется, вы пытаетесь сделать один класс одновременно базовым и фабричным. Не надо. Используйте 2 отдельных класса. Что-то вроде этого:

package Foo;

package Bar;
use base 'Foo';

package Baz;
use base 'Foo';

package Bazza;
use base 'Foo';

package Factory;
use Bar;
use Baz;
use Bazza;

sub get_foo {
    my ($class, $string) = @_;
    return Bar->try($string) || Baz->try($string) || Bazza->try($string);
}

А затем используйте это как:

my $foo = Factory->get_foo($string);

Таким образом, вашему базовому классу не нужно знать о ваших дочерних классах, только ваша фабрика. И дочерним классам также не нужно знать друг о друге, только Factory нужно знать подробности того, какие дочерние классы попробовать и в каком порядке.

1
mpeters 16 Июн 2009 в 15:56