Code Reviewでこの質問をしましたが、元のコードは現在忍び寄っています。はい、私は Clean code talk の大ファンでもあり、これらの素晴らしいビデオを見ました。この別の質問も見ました。これは、私が最初に抱えていた問題と同じです。
私は人間と言うクラスを持っています。人間は、その Travel メソッドでの決定に基づいて、Horse、Camel、または Ship To Travel を呼び出すか、(状況によっては) それらすべてに Travel を依頼することもできます。
Horse、Camel、Ship のすべてに ITransport インターフェイスがあり、もちろんこのインターフェイスには Travel メソッドがあります。
最初の問題は、私のプロジェクトの存続期間中に、飛行機、ロケット、潜水艦などの新しい輸送手段を手に入れる可能性があることです.
したがって、コンストラクターのパラメーターが膨張し続けるため、単純に ITransport 船、ITransport horse ..... などとしてコンストラクターに渡すことはできません。
そのため、HumanFactory にはイベントが必要であり、そのイベントは Human クラスのコンストラクターに渡される必要があるという提案 (と思います) の解決策に至りました。
私はどういうわけか私の巨大なトランスポート リストを削除しましたが、ご存知のように、インターフェイスには多くのメソッドを含めることができます。そのため、それぞれがインターフェイスのメソッドに対応し、もちろん必要に応じて、多数のデリゲートを渡す必要があります。
私は、正しいトランスポートにマップし、正しいイベントを呼び出すことだけを担当する Human Mapper クラスを作成することで、この問題を解決しようとさえしました。これはうまくいきます!
さて、これは架空の例であるため、実際の例ではインターフェイスのメソッドがパラメーターを受け入れるので、どのように対処すればよいでしょうか?
私が目指す方向はメンテナンスナイトメアを作ることだと思います。
クイックリファレンス用にコードを貼り付けています。
interface ITransport
{
void Travel();
}
私のトランスポートファクトリーは次のとおりです。
public class TransportFactory
{
....
internal ITransport ProvideTransport(TransportTypes transportType)
{
switch (transportType)
{
case TransportTypes.Camel: return new Camel();
case TransportTypes.Horse: return new Horse();
case TransportTypes.Ship: return new Ship();
default:
return null;
}
}
}
提案後の私のヒューマンクラスは次のようになりました。
public class Human
{
Action<Human, string> _transportRequested;
public Human(Action<Human, string> transportRequested)
{
_transportRequested = transportRequested;
}
public void Travel()
{
if (_transportRequested != null)
{
var ev = _transportRequested;
ev.Invoke(this, GroundTypes.Plains.ToString());
}
}
}
提案されているように、次のようなヒューマンクラスファクトリがあります。
public class HumanFactory
{
ITransport camel;
ITransport ship;
ITransport horse;
Human _human;
Dictionary<string, ITransport> _availableTransports;
event Action<Human, string> transportRequested;
public HumanFactory(TransportFactory tFactory)
{
horse = tFactory.ProvideTransport(TransportTypes.Horse);
camel = tFactory.ProvideTransport(TransportTypes.Camel);
ship = tFactory.ProvideTransport(TransportTypes.Ship);
}
public Human ConfigureHuman()
{
if (_availableTransports == null)
{
_availableTransports = new Dictionary<string, ITransport>();
_availableTransports.Add(GroundTypes.Desert.ToString(), camel);
_availableTransports.Add(GroundTypes.Sea.ToString(), ship);
_availableTransports.Add(GroundTypes.Plains.ToString(), horse);
}
transportRequested += new Action<Human, string>(_human_transportRequested);
_human = new Human(transportRequested);
return _human;
}
void _human_transportRequested(Human human, string groundType)
{
if (_availableTransports.ContainsKey(groundType))
{
ITransport suitableTransport = _availableTransports[groundType];
suitableTransport.Travel();
}
else
{
//code for handling below conditions goes here
//I don't know what to do for this type of plain?
}
}
}
私は、正しいトランスポートを正しいメソッドにマップする Mapper クラスについて話しました (見苦しく見えますが、それが私が思いついた最高のものでした:) ):
class Human_Transport_MethodMapper
{
Dictionary<GroundTypes, ITransport> _availableTransports;
List<EventTypes> _availableEvents;
event Action<Human, GroundTypes, EventTypes> transportRequested;
internal Action<Human, GroundTypes, EventTypes> transportRequesteddel;
public Human_Transport_MethodMapper(Dictionary<GroundTypes, ITransport> availableTransports, List<EventTypes> availableEvents)
{
_availableEvents = availableEvents;
_availableTransports = availableTransports;
transportRequested += human_OnAnyEventReceived;
transportRequesteddel = transportRequested;
}
internal void human_OnAnyEventReceived(Human human, GroundTypes groundType, EventTypes eventType)
{
if (_availableTransports.ContainsKey(groundType))
{
ITransport suitableTransport = _availableTransports[groundType];
switch (eventType)
{
case EventTypes.Travel: suitableTransport.Travel();
break;
default:
break; //meaning interface's correct method has not been mapped.
}
}
else
{
//code for handling below conditions goes here
//I don't know what to do for this type of plain?
}
}
}
このイベントで、Travel メソッドの引数が 2 つある場合、デリゲート シグネチャが変更されることを確認してください。
ここで私の問題を説明できたことを願っています。ありがとう
編集:読みやすくするために、この質問からいくつかの明白なコードを削除しています。また、より冗長になっています。