虽然我在Code Review中问过这个问题,但原始代码现在正在蔓延。是的,我也是清洁代码讲座的忠实粉丝,刚刚看了那些很棒的视频,我也看到了另一个问题。这与我最初遇到的问题相同。
我有一门课说人类。人类基于其 Travel 方法中的某些决定可以调用 Horse、Camel 或 Ship To Travel,也可以要求所有这些人(在某些情况下) Travel。
所有的 Horse、Camel、Ship 都有 ITransport 接口,当然这个接口有 Travel 方法。
最初的问题是,在我的项目的生命周期中,我可能会得到一些新的交通工具,比如飞机、火箭、潜艇等。
所以我不能简单地将它们作为 ITransport 船、ITransport 马......等在构造函数中传递,因为我的构造函数参数将继续膨胀。
因此,我按照建议(我认为)提出了一个解决方案,即 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?
}
}
}
现在看到在这种情况下,For Travel 方法如果有两个参数,那么委托签名会改变,如果 ITransport 接口中有四五个方法,那么请上帝帮助我。
我希望我已经在这里解释了我的问题。谢谢
编辑:我正在从这个问题中删除一些明显的代码,以使其更具可读性,而且它也变得更加冗长