虽然我在Code Review中提出了这个问题,但原始代码现在正在爬行。是的,我也是Clean Code讲座的忠实粉丝,刚刚观看了那些精彩的视频,我也看到了这个another question。这是我原来的问题。依赖注入,类需要相同类型的接口的字典是一个好主意?
我有一堂课说人。基于旅行方式中某些决定的人可以调用Horse,Camel或Ship To Travel,或者也可以让所有人(在某些情况下)去旅行。
所有的马,骆驼,船有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?
}
}
}
我谈过一个映射器类映射正确运输纠正方法为(它看起来很丑,但是那是最好的,我想出了:)):
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?
}
}
}
现在看到,在这种情况下,对于旅游法,如果有两个参数,那么委托签名就会改变,如果ITransport界面中有四五种方法,那么上帝可以帮助我。
我希望我在这里解释了我的问题。 感谢
编辑:我除去这个问题,一些明显的代码,以使其更具可读性,也被越来越冗长
如果我简单地传递一个Itransports字典及其类型(骆驼,马,船......等),它会违反Demeter法还是依赖注入法? – shankbond