.net 采用模板法和参数化工厂法进行再设计。依赖倒置
我决定使用最近获得的对设计模式的基本理解来重新设计某个子系统 我可以看到两种抽象,因此它们已成为接口。其中一个遵循模板方法(IAnalyzer)模式,因为它有用于各种场景的通用算法(只是基本操作不同),并将第二个抽象(解析器)提供的数据放入数据库。另一个抽象,IParser,连接到一些外部数据源并从中检索数据。 我还向项目中添加了参数化的Factory方法类,该类可以创建IParser实例和IAnalyzer实例。IAnalyzer包含对IParser的引用。(在我看来,这是一种策略,IAnalyzer作为上下文,IParser作为策略,但如果我错了,请纠正我。) 对于IParser的每个可能实现,都有一些包含连接信息的设置对象。现在,根据文献,我们可以向工厂模式传递一个参数,以便实例化一个对象。因此,我正在考虑将这些设置对象用作创建IParser的factory方法的参数。在下一步中,我将使用另一个factory方法,使用前面创建的IParser实例作为参数来创建IAnalyzer对象 (设置对象以序列化形式存储在磁盘上,目前不从任何对象继承。它们是否应该继承?)基本上,我在工厂方法中使用if-else-if逻辑检查传递对象的类型以创建解析器。每当需要创建新类型的解析器时,也需要创建相应的设置对象。因此,将新的else if语句添加到工厂方法将负责生成新的解析器。(实际上存在一对多关系btwn设置对象和解析器,b/c连接信息可能包含多个要连接到相同数据源的地址。因此factory方法可能会返回一个解析器数组。) 基于设置对象参数生成新类是否违反依赖倒置原则(抽象不应该依赖于细节,而应该依赖于抽象),您认为呢 下面是一些代码.net 采用模板法和参数化工厂法进行再设计。依赖倒置,.net,design-patterns,.net,Design Patterns,我决定使用最近获得的对设计模式的基本理解来重新设计某个子系统 我可以看到两种抽象,因此它们已成为接口。其中一个遵循模板方法(IAnalyzer)模式,因为它有用于各种场景的通用算法(只是基本操作不同),并将第二个抽象(解析器)提供的数据放入数据库。另一个抽象,IParser,连接到一些外部数据源并从中检索数据。 我还向项目中添加了参数化的Factory方法类,该类可以创建IParser实例和IAnalyzer实例。IAnalyzer包含对IParser的引用。(在我看来,这是一种策略,IAnal
public class DSParsersFactory
{
public static IParser[] CreateParsers(object ConnectionInfo)
{
if (ConnectionInfo == null) throw new ArgumentNullException();
List<IParser> retVal = new List<IParser>();
if (ConnectionInfo is MDSErverSettings)
{
//foreach address
MDSServerSettingsAdapter sa = new MDSServerSettingsAdapter(); //realizes IAdapterConnectionInfo
//init sa with current address
IParser p = CreateParser(sa);
if (p != null) retVal.Add(p);
}
else if (...)
return retVal.ToArray();
}
static IParser CreateParser(IAdapterConnectionInfo ia)
{
if (ia is MDSServerSettingsAdapter)
return new MDSParser(ia);
else if(...)
return null;
}
public static IAnalyzer CreateAnalyzer(IParser p)
{
if (p == null) throw new ArgumentNullException();
if (p is MDSParser) return new MDSAnalyzer(p);
else if (...)
return null;
}
}
除了最后一段和其他几段,我发现阅读你的问题真的很困难,但无论如何我都会尽力回答 从我在代码中看到的情况来看,您不应该使用
if
语句来确定IAdapterConnectionInfo
对象的类型,而应该为每种类型重载方法。这将极大地提高效率和可扩展性-我不知道这在您的模式中是否可行,但是如果从实现IAdapterConnectionInfo
的旧类继承一个新类,并且在ia is DerivedClass
之前检查了ia is OldClass
,您将失去特定性。CreateParsers
方法也是如此。调用方法可以处理问题,并在需要时使用RTTI和casting,但是您的类不再依赖于该设计,我认为这是一件好事
解决此问题的另一种方法是在IAdapterConnectionInfo
中创建一个方法,该方法返回正确的相关ServerSettingsAdapter
类型,并在(可能存在也可能不存在)IServerSettingsAdapter
中创建另一个方法,该方法返回相应的解析器类型。然后可以使用反射和投射来加载这些。这可能有效,也可能无效——我真的不知道
对不起,如果我没有回答正确的问题…:P为什么从CreateParsers()返回数组而不是IEnumerable?至少可以避免ToArray()调用并返回retVal本身。我会说数组作为返回类型,它是smth一样的旧样式,但这是我个人的观点,所以不在乎:)对不起,写得太乱了。图表还没有准备好。你是说重载私有静态CreateParser(…)方法吗?@Nickolodeon:是的,CreateParser
和CreateParser
。实际上,根据设计模式的文献,在客户端强制转换对象并不好。这就是为什么他们发明这些模式来制造弱耦合。我正在考虑修改所有这些设置类,让它们实现接口以返回连接集合(我猜这违反了开-关原则,他)。然后我将输入设置类作为接口。谢谢你的投入,minitech,它让我思考得更多。
var settings = Deserialize(path);
IParser [] pArr = DSParsersFactory.CreateParsers(settings);
foreach (IParser prs in pArr)
{
IAnalyzer algorithm = DSParsersFactory.CreateAnalyzer(prs);
if (algorithm != null)
{
int nSuccesses = algorithm.ProcessData();
string msg=string.Format("{0} records out of {1} were processed succussfully", nSuccesses, prs.GetDataCount());
EventLog.WriteEntry(Settings.Default.AppName, msg);
}
}