web-dev-qa-db-ja.com

具象クラスをポリモーフィックにするために空の抽象クラスがあっても大丈夫ですか

BEFORE:

1つのメソッド定義を持つインターフェースがあります

_public interface IDockable
{
    void Dock(DockerContainerConfig config);
}
_

私の最初の実装はすべて問題ありません

_public class DockerContainer : IDockable
{
    public void Dock(DockerContainerConfig config)
    {

    }
}

public class DockerContainerConfig
{ 
    //machine configuration properties here 
}
_

しかし、2番目の実装では、別の構成セットを使用する必要があることに気付きました。

_public class DockerMachine : IDockable
{
    public void Dock(DockerMachineConfig config)
    {

    }
}

public class DockerMachineConfig
{
    //machine configuration properties here 
}
_

後:

_Configuration Classes_をポリモーフィックにするために、親クラスを作成し、_Configuration Classes_に継承させる。

_public class DockerConfig
{

}

public class DockerMachineConfig : DockerConfig
{
    //machine configuration properties here 
}

public class DockerContainerConfig : DockerConfig
{
    //container configuration properties here 
}
_

これにより、インターフェースのメソッド定義も変更しました。

_public interface IDockable
{
    void Dock(DockerConfig config);
}
_

そして、具体的なクラスでは、構成クラスオブジェクトに対してキャストを実行しました。 2つの構成クラスはまったく異なり、一般的なものはありません。 1つはマシンを処理するためにマシン構成を必要とし、もう1つはコンテナを処理するためコンテナ構成を必要とします。しかし、どちらの方法でも、DockerContainerDockerMachineは同じことを行います。 "コンテナをマシン内にドッキング"。これは、DockerMachineが外部から物事を行い、DockerContainerが内部から物事を行うようなものです。あなたはアイデアを得ます:)

_public class DockerContainer : IDockable
{
    public void Dock(DockerConfig config)
    {
        DockerContainerConfig container = config as DockerContainerConfig;
    }
}

public class DockerMachine : IDockable
{
    public void Dock(DockerConfig config)
    {
        DockerMachineConfig machine = config as DockerMachineConfig;
    }
}
_

私がここで間違えたと思うのは2つあります。

  1. インターフェイスのメソッド定義をvoid Dock(DockerContainerConfig config);からvoid Dock(DockerConfig config);に変更しました
  2. 空の親クラス_public class DockerConfig{}_を作成して、_Configuration Classes_をポリモーフィックにできるようにしました

私が行った変更が優れた設計とベストプラクティスに準拠しているかどうかを知りたいのですが。

5
jmc
public interface IDockable<T>
{
    public void Dock(T config);
}

型パラメーターを指定することで、クラスのDockメソッド内で受け入れるパラメーターを指定できます。例:

public class DockerMachine : IDockable<DockerMachineConfig>
{
    public void Dock(DockerMachineConfig config)
    {
    }
}

public class DockerContainer : IDockable<DockerContainerConfig>
{
    public void Dock(DockerContainerConfig config)
    {
    }
}

これは私の個人的な好みの方法ですが、他にもたくさんの方法が考えられます。あなたが現在やっていることは、IDockableインターフェースに型パラメーターを指定することで間違いなく簡略化できます。

17
Nathangrad

実装固有の部分は、インターフェースの一部であってはなりません。代わりに、すべての特定の構成をコンストラクタパラメータとして使用します。

public interface IDockable
{
    void Dock();
}

public class DockerContainer : IDockable
{
    private DockerContainerConfig config;

    public DockerContainer(DockerContainerConfig config)
    {
        this.config = config;
    }

    ...
}

public class DockerMachine : IDockable
{
    private DockerMachineConfig config;

    public DockerMachine (DockerMachineConfig config)
    {
        this.config = config;
    }

    ...
}
9
Spotted