我有一个抽象类X
和一些扩展此类的类,称它们为A
,B
和C
。
在其他一些类Y
中,我有一些依赖于类类型的方法调用。 if-else语句如下所示:
public class Y implements InterfaceY {
public Y(){
}
public String doStuff (X x, Boolean flag) {
String s = "";
if (x instanceof A) {
doStuff((A) x));
} else if (x instanceof B) {
doStuff((B) x));
} else if (x instanceof C) {
doStuff((C) x, flag);
} else {
throw new Exeption();
}
return s;
private String doStuff(A a) {
return "";
}
private String doStuff(B b) {
return "";
}
private String doStuff(C c, Boolean flag) {
return "";
}
}
请注意,所有方法都具有相同的名称(doStuff()
),但根据类(有时是标志),调用该方法的不同方法实现。当然,这看起来很可怕,并且一旦从X延伸的分类增加,就会变得非常复杂。
有什么方法可以以某种方式创建一个中间接口(或其他东西)来处理大多数(或所有)if-else语句?
答案 0 :(得分:1)
首先将这些方法取出来,分别放入A,B和C类,实现X接口。
private String doStuff(A a) {
return "";
}
private String doStuff(B b) {
return "";
}
private String doStuff(C c, Boolean flag) {
return "";
}
然后:
if (x instanceof A) {
doStuff((A) x));
} else if (x instanceof B) {
doStuff((B) x));
} else if (x instanceof C) {
doStuff((C) x, flag);
可以只是x.doStuff();
(你甚至不必传递A,B,C,因为在方法中它将是this
。你将不得不乱用的旗帜依赖更具体地说,在您的代码上。例如,其他2个doStuff
方法也可以接受该标志,但只是忽略它。)
答案 1 :(得分:0)
APPROACH 1
使用state pattern。它会解决您的问题并消除if
和else
s。
这是java example。
状态模式将方法调用委托给实现相同接口但行为不同的对象。
状态模式示例:
public class StatePatternExample {
public static void main(String[] args) {
Girlfriend anna = new Girlfriend();
// OUTPUT
anna.kiss(); // *happy*
anna.greet(); // Hey, honey!
anna.provoke(); // :@
anna.greet(); // Leave me alone!
anna.kiss(); // ...
anna.greet(); // Hey, honey!
}
}
interface GirlfriendInteraction extends GirlfriendMood {
public void changeMood(GirlfriendMood mood);
}
class Girlfriend implements GirlfriendInteraction {
private GirlfriendMood mood = new Normal(this);
public void provoke() {
mood.provoke();
}
public void kiss() {
mood.kiss();
}
public void greet() {
mood.greet();
}
public void changeMood(GirlfriendMood mood) {
this.mood = mood;
}
}
interface GirlfriendMood {
public void provoke();
public void kiss();
public void greet();
}
class Angry implements GirlfriendMood {
private final GirlfriendInteraction context;
Angry(GirlfriendInteraction context) { // more parameters, flags, etc. possible
this.context = context;
}
public void provoke() {
System.out.println("I hate you!");
}
public void kiss() {
System.out.println("...");
context.changeMood(new Normal(context));
}
public void greet() {
System.out.println("Leave me alone!");
}
}
class Normal implements GirlfriendMood {
private final GirlfriendInteraction context;
Normal(GirlfriendInteraction context) {
this.context = context;
}
public void provoke() {
System.out.println(":@");
context.changeMood(new Angry(context));
}
public void kiss() {
System.out.println("*happy*");
}
public void greet() {
System.out.println("Hey, honey!");
}
}
如您所见,课程Girlfriend
没有if
和else
。它看起来很干净。
班级Girlfriend
对应于您的abstract class X
,班级Normal
和Angry
对应A
,B
和{{1} }。
您的班级C
然后直接委托给X而不检查任何案件。
APPROACH 2
使用command pattern。然后,您可以将命令对象移交给Y
的{{1}}方法,然后执行它。
答案 2 :(得分:0)
如何实现Handler
接口,然后按支持的类型映射它:
public interface Handler<T extends X>{
Class<T> supportedClass;
void doStuff(T value, Object...args);
}
public class Y implements InterfaceY {
private Map<Class<?>, Handler<?>> handlers;
public Y(List<Handler<?>> handlers){
// populate map
}
public void process(X value){
handler.get(value.getClass).doStuff(X, ...);
// you would have to figure out how to determine when other values are needed
}
}
答案 3 :(得分:0)
某些double dispatch呢?
class X {
public String letYdoStuff(Y y, Boolean flag) {
return y.doStuff(this, flag);
}
public static void main(String [] args) {
//X x = new A();
X x = new B();
Y y = new Y();
y.doStuff(x, false);
}
public X getThis() {
return this;
}
}
class A extends X {
public String letYdoStuff(Y y, Boolean flag) {
return y.doStuff(this, flag);
}
}
class B extends X {
public String letYdoStuff(Y y, Boolean flag) {
return y.doStuff(this, flag);
}
}
class C extends X {
public String letYdoStuff(Y y, Boolean flag) {
return y.doStuff(this, flag);
}
}
class Y {
public Y(){
}
public String doStuff (X x, Boolean flag) {
String s = "";
return x.letYdoStuff(this, flag);
}
public String doStuff(A a, Boolean flag) {
System.out.println("in A");
return "";
}
public String doStuff(B b, Boolean flag) {
System.out.println("in B");
return "";
}
public String doStuff(C c, Boolean flag) {
System.out.println("in C");
return "";
}
}
答案 4 :(得分:0)
这可能是一个难题。我认为克朗彻的解决方案,补充道
doStuff
到X并在A
,B
,C
覆盖它是最简单的
适当时的最佳解决方案。然而,并非总是如此
适当的,因为Single responsibility
principle。
(我认为这是正确的用语。如果我得到一些,我道歉
术语错了,我并不完全了解所有条款。)
我们的想法是,如果有doStuff
,则不一定X
与X
的目的无关。如果X
和Y
是其中的一部分
同样的“团队”,即他们都是为了一个人的目的而设立的
特别的应用,然后它可能没问题。
但假设您有一个具有子类的抽象Shape
类
Circle
,Square
,Undecagon
,RandomBlob
等等
属于Shape
类的一些方法对我们有用
任何使用Shape
类的应用程序。但现在说你是
写一个使用其中一些形状的游戏,你想要一个
多态操作,确定形状得到时会发生什么
被飞猴吃掉了。您不希望添加摘要
computeEatenByFlyingMonkey
课程的Shape
方法即使是doStuff
课程
上课是你自己的创作而不是别人的图书馆,
因为那对于一个可能的类来说太具体了
通常用于除了这一场比赛之外的其他目的。
我可以想到几种方法来解决这个问题。
如果将X
添加到A
是不合适(或不可能),但是
如果B
,C
和doStuff
与您的应用程序关联得更紧密
向他们添加public abstract class XWithStuff extends X {
// repeat any constructors in X, making them all be just
// calls to super(...)
public abstract void doStuff (Boolean flag);
}
public class A extends XWithStuff {
@Override
public void doStuff (Boolean flag) { ... }
}
是合适的,您可以添加另一个
class:
XWithStuff
以及其他所有课程。 (Boolean
只是一个例子
名称;在现实生活中,一个包含“X”和一些参考的名称
申请或目的可能更好。)(P.S。我不知道
为什么你使用的是boolean
而不是doStuff
,但我要离开它
这种方式,以防有充分的理由。)
如果将A
添加到B
也不合适或不合适,
C
和public interface StuffInterface {
public void doStuff (Boolean flag);
}
public class AWithStuff extends A implements StuffInterface {
@Override
public void doStuff (Boolean flag) { ... }
}
,这是一个可能的解决方案:
AWithStuff
然后在你的程序中创建类A
的对象
在doStuff
上致电X
:
void doStuff (X x, Boolean flag) {
if (x instanceof StuffInterface) {
((StuffInterface) x).doStuff (flag);
} else {
throw new IllegalArgumentException ();
}
}
等
A
如果这不是一个选项,您必须直接与B
,doStuff
打交道,
等,你不能将if
添加到这些类,然后任何解决方案
会有点hacky。如果您不想使用then
- else
- HashMap<Class<?>,Interf>
,那么
可以查看visitor pattern,或者你可以想象创建
一个A.class
,用于映射B.class
,doStuff
,
等,调用正确的{{1}}的某个接口对象。但
我还没有弄清楚细节。 (实际上,除非你有某种由X型对象组成的复杂结构,否则“访客模式”可能不合适。)
答案 5 :(得分:0)
分隔DoStuffOperation
,创建相关工厂并使用它们。
public interface DoStuffOperation<T> {
String doStuff(T x);
}
public class ADoStuffImpl implements DoStuffOperation<A> {
public String doStuff(A x) {
return "doStuff<A>";
}
}
public class ADoStuffWithFlagImpl implements DoStuffOperation<A> {
public String doStuff(A x) {
return "doStuffWithFlag<A>";
}
}
public class DoStuffImplFactory {
public final static <T extends X> DoStuffOperation<X> getDoStuff(Class<T> xClass,boolean flag) {
DoStuffOperation<X> impl = null;
if(xClass.equals(A.class))
{
if(flag)
impl = (DoStuffOperation)new ADoStuffWithFlagImpl();
else
impl = (DoStuffOperation)new ADoStuffImpl();
}
}
return impl;
}
}
public class Y implements InterfaceY {
public String doStuff (X x, Boolean flag) {
return DoStuffImplFactory.getDoStuff(x.getClass(),flag).doStuff(x);
}
}
通过这种方式,您无需重构对Y.doStuff()
或X
及派生类的调用。
除非instanceof
类实现DoStuffCreator接口,否则您无法删除某些doStuff()
来确定X
的哪个实现使用:
interface DoStuffCreator {
DoStuffOperation getDoStuffOperation(boolean flag);
}
X
和A
是您的课程。您还可以使用反射或其他自动方式(外部属性文件等)构建。