3

以下のパターンを探しています。(私は Perl で作業していますが、言語は特に問題ではないと思います)。

親クラスが Foo で、子クラスが Bar、Baz、Bazza です。

Foo を構築する方法の 1 つは、文字列を解析することです。その文字列の一部は、作成するクラスを暗黙的に指定します。たとえば、「http:」で始まる場合はバーですが、そうではなく「[Date]」が含まれている場合、Baz はそれを好みます。

ここで、Foo がそのすべての子について知っていて、どの文字列が Bar で、何が Baz であるかなどを知っている場合、適切なコンストラクターを呼び出すことができます。ただし、基本クラスはその子に関する知識を持ってはいけません。

私が望むのは、Foo のコンストラクターがその子を順番に試すことができるようにすることです。そのうちの 1 つが「はい、これは私のものです。私が作成します」と言うまでです。

文字列を受け入れる子が複数存在する可能性があるため、一般的なケースでは、この問題は明確に定義されていないことを認識しています。したがって、それらが呼び出される順序が重要です。これを無視して、文字列の特性が1 つの子クラスだけがその文字列を好むようなものです。

私が思いついた最善の方法は、子クラスが初期化時に基本クラスに「登録」して、コンストラクターのリストを取得し、それらをループすることです。しかし、私が見逃しているより良い方法はありますか?

サンプルコード:

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;
}
4

4 に答える 4

5

おそらく、 Module :: Pluggableでこれを実装できますか?これにより、登録の必要がなくなります。

私が以前に採用したアプローチは、Module :: Pluggableを使用して子モジュールをロードすることでした(これにより、子モジュールを作成してインストールするだけで、新しい子モジュールを追加できました)。各子クラスには、祝福されたオブジェクトまたはundefを返すコンストラクターがあります。オブジェクトを取得するまでプラグインをループし、それを返します。

何かのようなもの:

package MyClass;
use Module::Pluggable;

sub new
{
    my ($class, @args) = @_;
    for my $plugin ($class->plugins)
    {
       my $object = $plugin->new(@args);
       return $object if $object;
    }
}

Class:Factoryもありますが、それはあなたのニーズを少し上回っているかもしれません。

于 2009-06-16T12:03:43.833 に答える
1

単一のクラスを基本クラスとファクトリの両方にしようとしているようです。しないでください。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 だけが、どの子クラスをどの順序で試すかの詳細を知る必要があります。

于 2009-06-16T15:56:54.973 に答える
0

既存の子クラスを検索する任意のルックアップ アルゴリズムをクラス Foo に実装できます。おそらく、子クラスで提供される構成ファイル、または考えられるその他のメカニズムに基づいています。

クラス Foo は実行時に既存のクライアント クラスを検出し、それらを順番に呼び出します。

さらに、検索結果をキャッシュして、既に説明したレジストリ ソリューションに近づくこともできます。

于 2009-06-16T11:31:11.510 に答える
0

子に関する情報が含まれていない親クラスについてのコメントと、子クラスの適合性をクラス自体に確立するタスクを委任する方法についてのコメントを受け取る場合、親クラスからクラスの選択を除外して作成するのがおそらく正しいでしょう。このタスクのシングルトン。

少なくともそれは私の好みです...これから、現在の親クラス(おそらく子クラス全体でいくつかの共通の機能を持っている)は、おそらく抽象またはインターフェースのいずれかになります。

シングルトンは、すべての子クラスの構築とその配布を管理できます(機能しない場合はクローンを作成しますか?)...さらに、子クラスを別のdllに移動して、分離を促進できます。

申し訳ありませんが、それは直接的な解決策ではありません。あなたがここにいるのと同じように、シングルトンでクラスのリストを管理することで、過去にこれを行いました。シングルトンの背後にある考え方は、高価なリフレクションを使用したい場合は、一度だけ実行する必要があるということです。

于 2009-06-16T12:26:37.563 に答える