上記のようなものを実装する方法はいくつか考えられます。
1. インターフェイスを使用する
元のソース コードを変更できる場合は、おそらくこれが最適なオプションです。実装が簡単で、保守も簡単です。
public interface IDoSomething
{
void DoSomething();
}
public class Dog : Animal, IDoSomething
{
public void Bark()
{
}
void IDoSomething.DoSomething(){
Bark();
}
}
public class Cat : Animal, IDoSomething
{
public void Meow()
{
}
void IDoSomething.DoSomething(){
Meow();
}
}
元のソース コードにアクセスできない場合は、アダプターが唯一の選択肢となる場合があります。これらを使用して、コードが Cat および Dog クラスにアクセスする方法を「同期」できます。元のオブジェクトであるかのようにアダプターを操作できますが、新しいコードのニーズにより適した変更されたインターフェイスを使用できます。親タイプに基づいて適切なアダプターを作成するためのファクトリーを作成するのはかなり簡単です。
public IDoSomething
{
void DoSomething()
{
}
}
public DoSomethingFactory
{
public static IDoSomething( Animal parent )
{
if ( typeof( parent ) is Dog )
return new DoSomethingDog( parent as Dog );
if ( typeof( parent ) is Cat )
return new DoSomethingCat( parent as Cat );
return null;
}
}
public DoSomethingDog : Dog, IDoSomething
{
Dog _parent;
public DoSomethingDog( Dog parent )
{
_parent = parent;
}
public void DoSomething()
{
_parent.Bark();
}
}
public DoSomethingCat : Cat, IDoSomething
{
Cat _parent;
public DoSomethingCat( Cat parent )
{
_parent = parent;
}
public void DoSomething()
{
_parent.Meow();
}
}
これら 2 つの明白な実装とは別に、次のことを検討することをお勧めします。
デコレーターを使用して、クラスの機能を動的に強化します。(上記の「ラッパー」アプローチに似ていますが、クラス構造にもう少しきれいに焼き付けられています。)
クラスが動的に処理できる一連のCommandオブジェクトを実装します。
cat.Do( new MakeNoiseCommand() ); // Handled as "meow"
dog.Do( new MakeNoiseCommand() ); // Handled as "bark"
動物のタイプなどに基づいてリクエストを転送するメディエーターに似たものを許可します。
public class AnimalMediator
{
public void MakeNoise( Animal animal )
{
if ( typeof( animal ) is Dog ) (animal as Dog).Bark();
else if ( typeof( animal ) is Cat ) (animal as Cat).Meow();
}
}