我希望你能解决我的问题:
我有一个班级做肥皂调用。但是如果肥皂定义发生变化,我将不得不写一个新的类或继承它。 所以我开始写解决方案来写这样的东西:
switch(version)
{
case "1.0":
saopV1.getData()
case "2.0":
soapV2.getData()
}
非常糟糕的代码,我知道。然后我读到了战略模式,我想,哇,这就是我需要摆脱这个糟糕的开关案例的事情:
abstract SoapVersion
{
public SoapVersion GetSoapVersion(string version)
{
//Damn switch-case thing
//with return new SoapV1() and return new SoapV2()
}
public string[] virtual getData()
{
//Basic Implementation
}
}
class SoapV1:SoapVersion
{
public override string[] getData()
{
//Detail Implementation
}
}
class SoapV2:SoapVersion
{//the same like soapv1}
但是我无法避免在我的代码中使用“ifs”或切换案例。这可能是使用OO技术??
编辑: GetSoapVersion-Function应该是静态的
答案 0 :(得分:4)
这或多或少是以美丽的方式做到这一点的正确方法。 在代码中的某个时刻,您必须决定是否必须使用v1或v2,因此无论如何您都必须拥有条件语句(if或switch)。但是,在使用策略和工厂(工厂方法或工厂类)时,您已经集中了这一决定。
我会在抽象类上生成我的工厂方法静态。 此外,我将使用模板方法模式:即一个公共的,不可覆盖的GetData方法,该方法调用应在具体实现中覆盖的受保护虚拟(抽象)方法。
public abstract class SoapProcessor
{
protected SoapProcessor() { /* protected constructor since public is of no use */ }
public static SoapProcessor Create( SoapVersion version )
{
switch( version )
{
case SoapVersion.Version1 : return new SoapV1Processor();
case SoapVersion.Version2 : return new SoapV2Processor();
default: throw new NOtSupportedException();
}
}
public string[] GetData()
{
return GetDataCore();
}
protected abstract GetDataCore();
}
}
答案 1 :(得分:1)
如果您只在工厂或代码中使用了switch-cases,则会有所不同。您可以在一个点上做出决定(选择哪种实施方案)。
答案 2 :(得分:1)
在类似情况下,我使用以下标准在反射和if/case
之间进行选择:如果应该动态添加新版本支持(如插件),我选择反射,否则 - if/case
。正如在其他答案中提到的那样,它应该在工厂方法中提供单个地方来创建东西。值得一提的是Strategy
是一种行为模式,而你所要求的似乎是创造性的。
答案 3 :(得分:1)
您不需要切换或if语句
只需使用委托
即抽象类的具体实现将根据需要执行(即SoapV1,SoapV2等),客户端在对象引用中设置适当的实例。
您只有对基类的引用,并且客户端设置了相应的子类。您的代码只调用基类的方法(在运行时是派生的实现之一)。例如。一个例子(免责声明:没有编译代码。只有一个样本)
public abstract class SoapHandler
{
protected abstract string[] getData();
}
public class SoapHandlerV1 extends SoapHandler
{
public string[] getData(){
//V1 implementation
}
}
public class SoapHandlerV2 extends SoapHandler
{
public string[] getData(){
//V2 implementation
}
}
public class SoapProcessor{
public SoapHandler soapHandler;
public setSoapHandler(SoapHandler h)
{
soapHandler = h;
}
public String[] getData(){
//delegate to specific version
soapHandler->getData();
}
}
//in your code
SoapProcessor soap = new SoapProcessor();
soap.setSoapHandler(new SoapHandlerV1());
String[] soapData = soap.getData();//Will get the appropriate version
//use soap data
//do stuff
检查GoF的示例以获取策略以查看我的意思,如果不清楚
答案 4 :(得分:0)
因为version
仅在运行时已知,所以它肯定会归结为某些条件(如果或切换或使用字符串和原型之间的映射等)。
因此,有价值的目标是减少条件数量/隔离变化点。
答案 5 :(得分:0)
你应该program to an interface not an implementation。
有一个单独的服务界面,您可以从客户端使用。
public interface IService
{
string[] GetData();
}
并将您的客户编码为 -
IService srvice = ServiceFactory.GetProxy();
string[] value = service.GetData();
这样,当服务代理更改时,您的客户端代码不会更改。
然后您可以开始使用条件逻辑来创建适当的代理到ServiceFactory
类。稍后您可以使用以下技术更改它以删除条件逻辑,例如 -