0

最初に、タイトルが少しわかりにくい場合は申し訳ありません。

小さな erp アプリケーションを開発する予定です。このアプリケーションはプラグイン/アドオンを使用します。このアドオンは、ベース アプリケーションの一部のモジュールを追加または拡張する場合があります。

たとえば、プロパティ「id」と「name」を持つ TCustomer クラスがあります。アドオン 1 はプロパティ「生年月日」を追加します。アドオン 2 は、プロパティ「balance」とメソッド「GetBalance」を追加します。

アドオン 1 とアドオン 2 はお互いを認識していません。アドオン 1 がインストールされていて、アドオン 2 がインストールされていない、またはその逆の場合があります。したがって、両方のアドオンが基本の tcustomer クラスを継承する必要があります。

問題は、両方のアドオンがインストールされている場合です。両方のアドオンで拡張プロパティを取得するにはどうすればよいですか? 新しいプロパティを表示するコントロールを追加するには、フォームを拡張する必要もあります。

それはデルフィを使用して行うことができますか?これを達成するための最良の方法は何ですか?いくつかの例の記事を教えていただけますか?

私の貧弱な英語のレイナルディに感謝し、申し訳ありません

4

2 に答える 2

5

既にお気づきのように、既存のクラスを継承によって拡張するプラグインを複数持つことはできません。プログラマーがコードを扱う場合を含め、アプリ全体を混乱させる可能性があります。

必要なのは、すべてのプラグインが特定のプロパティを登録できる、または TCustomer インスタンスが作成 (初期化)、ロード、保存、または削除されたときにいくつかのコールバック関数を提供できる、TCustomer クラスのある種の登録メカニズムです。結局、コアの TCustomer は、プラグインが存在する可能性があるという事実以上に、プラグインについて詳しく知る必要はありません。

データをどのようにロード/保存するかによって、コア TCustomer クラスは拡張子を認識する必要さえありません。永続化メカニズムにプラグインを認識させ、TCustomer / TOrder / TWhatever が初期化 / ロード / 保存 / 削除されるたびに呼び出されるコールバック関数を登録する方法を提供するだけで十分です。

また、GUI にプラグインを認識させ、UI の一部を登録してメイン GUI に各プラグインの特定のコントロール用に追加のタブなどを作成させる手段を提供する必要があります。

コード例がありません。これはまだ自分で実装していませんが、デザインについて考えてみましたが、これは私の遊びのリストに載っています。

とはいえ、基本的なメカニズムは次のようになります。

TBaseObject = class; // forward declaration

// Class that each plug-in's extensions of core classes needs to inherit from.
TExtension = class(TObject)
public
  procedure Initialize(aInstance: TBaseObject);
  procedure Load(aInstance: TBaseObject);
  procedure Store(aInstance: TBaseObject);
  procedure Delete(aInstance: TBaseObject);
end;

// Base class for all domain classes
TBaseObject = class(TObject)
private
  MyExtensions: TList<TExtension>;
public
  procedure RegisterExtension(const aExtension: TExtension);
  procedure Store;
end;

procedure TBaseObject.RegisterExtension(const aExtension: TExtension);
begin
  MyExtensions.Add(aExtension);
end;

procedure TBaseObject.Store;
var
  Extension: TExtension;
begin
  // Normal store code for the core properties of a class.
  InternalStore; 
  // Give each extension the opportunity to store their specific properties.
  for Extension in MyExtensions do
    Extension.Store(Self);
end;
于 2012-05-12T16:53:28.467 に答える
1

このような「進化する」クラスは、ある種の多重継承です。

クラスではなくインターフェイスを使用する方がよいと思います。

つまり、各プラグインはクラスの実装を提供しますが、インターフェイスとインターフェイス ファクトリを操作します。

「インターフェイスが必要な理由」に関するこの記事、またはインターフェイスとクラスとの比較に関するブログのこの記事を参照してください。

クラスがインターフェースを実装しているかどうかをテストできます。あなたのようなプラグイン システムでは、これがおそらくオープンな実装を実装する最良の方法です。ダックタイピングはプラグインに非常に適しています。Delphi IDE 全体(および Windows 自体)は、そのプラグイン システム用のインターフェイスを(COM for Windows 経由で)使用しています。あまり強力でない実装パターンについては、インターフェイスではなくレイト バインディングを使用できます。この SO の質問の回答を参照してください。

SOLID の原則、特に単一責任の原則に注目してください。あなたの質問は、この原則に直接違反しています。クライアントの個人情報 (名前など) と会計 (残高など) を混在させようとしています。プロジェクトが大きくなると、そのような設計に行き詰まる可能性があります。

于 2012-05-13T15:36:16.520 に答える