6

私は今日、 Composition over Inheritanceについて少し学びました。最近書いたものにその概念を適用するべきかどうか疑問に思っていました。

以前は、いくつかの小さな違いを除けば、ほぼ同じ2 つのクラスがありました。それらにはいくつかの基本的なデータベース アクセス機能が含まれていましたが、異なる (しかし関連する) オブジェクト タイプで動作していました。したがって、以前は次のような構造のクラスがありました。

class BallMillDBHandler{

    public BallMillDBHandler(){ ... }

    public void InsertTool(BallMill tool) { ... }
    public BallMill QueryTool(string toolID) { ... }
    public void UpdateTool(BallMill tool) { ... }
    public void DeleteTool(string toolID) { ... }
}

class DiamondToolDBHandler{

    public DiamondToolDBHandler(){ ... }

    public void InsertTool(DiamondTool tool) { ... }
    public DiamondTool QueryTool(string toolID) { ... }
    public void UpdateTool(DiamondTool tool) { ... }
    public void DeleteTool(string toolID) { ... }
}

ほとんど重複しているメソッドの大部分をクラスにリファクタリングしBaseToolDBHandler()、他の 2 つのメソッドから継承して、データベース パラメータ自体へのアクセスの違いを処理するためのいくつかの抽象メソッドとプロパティを提供しました。

BaseToolDBHandler代わりにヘルパー クラスを作成し、データベース アクセサー内に含めて、以前は抽象化されていたプロパティ/メソッドに共通のインターフェイスを提供することは理にかなっていますか? それとも継承のケースとして残すべきですか?

4

4 に答える 4

3

これは、基本クラス/インターフェイスを介したジェネリックと継承の両方にメリットがあるシナリオのように見えます。

class DBHandler<TTool> where TTool : ToolBase // or ITool
{
    public DBHandler(){ ... }

    public void InsertTool(TTool tool) { ... }
    public TTool QueryTool(string toolID) { ... }
    public void UpdateTool(TTool tool) { ... }
    public void DeleteTool(string toolID) { ... }
}

必要に応じて、ベース (オプションで抽象) クラス、またはメソッド本体内にツールが必要とする特定のメンバーを保証する型制約として使用するインターフェイスを作成できます。

例:

var handler = new DBHandler<BallMill>();
BallMill value = handler.QueryTool("xyz");
value.SomeProperty = "New Value";
handler.UpdateTool(value);
于 2012-09-25T14:36:00.293 に答える
3

継承は多用される傾向がありますが、これは適切なケースのようです。多くの場合、人々は重複したコードを見て、「継承を使用して基本クラスから重複したコードを削除しよう」と考えるだけです。実際には、ほとんどの重複コードは、複数の場所で使用される別のクラスに完全にリファクタリングできます。通常、それを使用するクラスは「関連」しておらず、2 つのまったく異なることを行っており、たまたまいくつか (または一連の) 小さなタスクを実行する必要性を共有しています。

クラスクラスが他の場所で定義された一連のメソッドへのアクセスを必要とするクラスだけでなく、クラスクラスが基本クラスのインスタンスであると実際に言うことができる場合、継承を使用する必要があります。あなたの特定のケースでは、両方のクラスがDB ハンドラーであることは明らかです。核心では、どちらも同じ一般的な目標を達成していますが、その目標の 2 つの異なる実装が可能です。ここで私が見ることができる唯一の問題は (どのメソッドの内容も示していないことを考えると)、両方のクラスを 1 つのクラスに結合できる可能性があることですが、その詳細についてもっと知る必要があります。それが可能かどうか、または望ましいかどうかを知ってください。

于 2012-09-25T14:35:25.093 に答える
0

これは間違いなく継承のタスクだと思います...しかし、最初に1つのことをまっすぐにしましょう。コンポジションは、クラスの多重継承が特定の言語 (C# など) の機能ではない場合に使用でき、また使用すべきデザイン パターンです。

コンポジションとは、Composite クラスがクラスをインスタンス化することを意味し、通常はクラスが継承されます。この例では、インターフェイスを介して実装にコントラクトを提供します。

継承をコードに適用する方法の大まかな例を示すために、次のことを考慮してください: (これは合成を使用していません)

public interface IHandler
{
    void InsertTool(ITool tool);
    void UpdateTool(ITool tool);
    void DeleteTool(string toolID);
    //void DeleteTool(ITool tool) - seems more consistent if possible!?

    ITool QueryTool(string toolID);
}

public interface ITool
{

}

class BallMill : ITool
{
}

class DiamondTool : ITool
{
}

class BallMillDBHandler : IHandler
{

    public BallMillDBHandler(){ ... }

    public void InsertTool(ITool tool) { ... }
    public BallMill QueryTool(string toolID) { ... }
    public void UpdateTool(ITool tool) { ... }
    public void DeleteTool(string toolID) { ... }
}

class DiamondToolDBHandler : IHandler
{

    public DiamondToolDBHandler(){ ... }

    public void InsertTool(ITool tool) { ... }
    public DiamondTool QueryTool(string toolID) { ... }
    public void UpdateTool(ITool tool) { ... }
    public void DeleteTool(string toolID) { ... }
}
于 2012-09-25T14:39:14.983 に答える
0

継承ではなく、ジェネリックを使用します。さまざまなタイプのオブジェクトに対して同じ操作を実行したい場合、これはまさにジェネリックが最も得意とすることです。

于 2012-09-25T14:40:05.873 に答える