我有一个包含几个重载方法的类,例如:
interface SharedInterface
{
public void commonMethod();
}
class Model1 implements SharedInterface
{
public void commonMethod(){}
public int foo(){ return 1; }
}
class Model2 implements SharedInterface
{
public void commonMethod(){}
public String bar(){ return "2"; }
}
class Client
{
private ExternalClass external = new ExternalClass();
public void handle( Model1 model )
{
external.calculate( model.foo() );
}
public void handle( Model2 model )
{
external.calculate( model.bar() );
}
}
我想让Client类更通用,以便将来可以处理任何类型的Model。但是,因为每个Model都有自己特定的公共方法,所以Client.handle()方法需要根据给定的Model更改其行为。例如,如果给出了Model1实例,则调用该模型的方法foo();如果给出了Model2实例,则调用方法bar()等。将来会创建更多类型的模型。以下解决方案打破了开放的封闭原则,似乎是一种非常糟糕的做法:
class Client
{
private ExternalClass external = new ExternalClass();
public void handle( SharedInterface model )
{
if( model instanceof Model1 )
external.calculate( model.foo() );
else if( model instanceof Model2 )
external.calculate( model.bar() );
}
}
我正在考虑使用泛型,但我不确定泛型如何解决这个问题。
请注意,Client类具有依赖项(使用库)。模型必须是POJO,不依赖于任何其他类。因此,由于Client.handle()的实现使用了这些依赖项,因此无法在Model类中移动该方法。
有人可以提供一些替代方案吗?
答案 0 :(得分:1)
访客设计模式最适合您的问题...链接可以帮助您 https://sourcemaking.com/design_patterns/visitor ..
答案 1 :(得分:1)
您的处理逻辑因每种类型而异,并且必须在某处描述不同的行为,对于您添加的每个Model
,您必须拥有一条处理逻辑,这是的完美案例重载 - 您已在第一个代码位中执行此操作。
如果您已经确定Client
清除这些实施。您可以在数据POJO的包装器(适配器)中定义不同的处理逻辑,并将它们传递给handle()
,例如:
class Client {
private ExternalClass external = new ExternalClass();
public void handle(PojoAdapter<?> model) {
model.getExecuted(external);
}
}
// Actually, generics are not necessary here, just to
// avoid declaring the same model field with different type
// in each implementation
abstract class PojoAdapter<T extends SharedInterface> {
protected T model;
public PojoAdapter(T model) {
this.model = model;
}
public abstract void getExecuted(ExternalClass excls);
}
class Model1Adapter extends PojoAdapter<Model1> {
@Override public void getExecuted(ExternalClass excls) {
external.calculate(model.foo());
}
}
class Model2Adapter extends PojoAdapter<Model2>{
@Override public void getExecuted(ExternalClass excls) {
external.calculate(model.bar());
}
}