我正在开发一个WCF Web服务,该服务根据string providerCode
从几个数据库之一返回信息。
在最高级别,该服务会调用StaticBroker
类,该类会检查providerCode
并返回DataManager
的相应子类,假设为MyDataManager
。然后,该服务调用MyDataManager.getVehicleFetcherForStop()
,它返回一个类VehicleInfoFetcher
的实例,用于获取信息。
我对这一切都很陌生,而且我认为我可能错误地构建了它。这是我现在如何做的代码(简化):
Service.svc.cs
// Public-facing web service method
public string getRealtimeInfo(String stopID, string providerCode = "UK")
{
DataManager dm = StaticBroker.Instance.dataManager(stopID);
return dm.getUpcomingVehicleInfoNow(primaryCode);
}
StaticBroker
public sealed class StaticBroker
{
UKDataManager ukDataManager = null;
// Create one instance of each data manager when the Web Service is started,
// to save memory
private StaticBroker()
{
ukDataManager = new UKDataManager();
}
public DataManager dataManager(string providerCode)
{
if (providerCode.Equals(UKDataManager.DEFAULT_PROVIDER_CODE))
return ukDataManager;
// else if...
}
// Most singleton stuff snipped out
private static readonly StaticBroker instance = new StaticBroker();
}
UKDataManager
public class UKDataManager : DataManager
{
public const string DEFAULT_PROVIDER_CODE = "UK";
public string getUpcomingVehicleInfoNow(string stopID)
{
VehicleInfoFetcher infoFetcher;
if ( shouldCheckDB(stopID))
VehicleInfoFetcher infoFetcher = new DatabaseVehicleInfoFetcher("UK");
else
fetcher = new UKLiveVehicleInfoFetcher();
return fetcher.getVehicleInfo(primaryCode).Result; // This is an async method, but we wait for the result
}
}
}
正如您所看到的,我有一个StaticBroker
的单例,它本身只存储每种DataManager
类型的一个实例。最后,在DataManagers中,创建了实际工作的类SomeVehicleFetcher
的实际实例。
这是一种明智的做法吗?或者,当Web服务的并发使用率很高时,这些单身人士和共享实例是否会导致问题?我担心创建大量新实例可能会导致内存问题。正如您所看到的,我并不真正理解应用程序的生命周期/内存周期在Web服务中是如何工作的。
答案 0 :(得分:3)
您正在尝试使用您不相信正确或需要的设计来解决假设性问题(“可能导致内存问题”)。此外,ADO.NET还有大量优化处理数据库连接性能。
这只是创造了更多的工作和更多的测试难题(你将如何隔离依赖于这个代理的代码?)。
请参阅反模式:
过早优化,未在此发明
修改强>
public interface IVehicleInfoRetriever {
VehicleInfoResponse getVehicleInfo(string primaryCode);
}
public class DataManager<TVehicleInfoFetcher>
where TVehicleInfoFetcher : class, new(), IVehicleInfoRetriever
{
private string _providerCode;
public DataManager() : this("UK") { }
public DataManager(string providerCode) {
_providerCode = providerCode;
}
public string getUpcomingVehicleInfoNow(string stopID)
{
VehicleInfoFetcher infoFetcher;
if ( shouldCheckDB(stopID))
VehicleInfoFetcher infoFetcher = new DatabaseVehicleInfoFetcher(_providerCode);
else
fetcher = new TVehicleInfoFetcher();
return fetcher.getVehicleInfo(primaryCode).Result; // This is an async method, but we wait for the result
}
}
}
这样的东西消除了对'经纪人'的需求。
另外,你称之为'Broker'的类更像是一个工厂而且工厂已经失宠了,因为它们允许在杂草中而不是在顶部指定依赖注入,并且它们进行环境配置单元测试复杂的事业。
当然,DataManager的风格可能与您展示的有很多不同。如果是这种情况并且它们无法集中,那么我建议您调查可用的许多Inversion Of Control容器之一(AutoFac,Unity,Castle Windsor)。这些容器将根据最顶层的提供者代码的运行时值保留DataManager使用的风格逻辑。