V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
XiaST
V2EX  ›  Java

在 Java 语言中有一堆 instanceof 的 else-if 语句,该如何重构才能使代码更加美观并且效率更快??

  •  
  •   XiaST · 2016-04-12 09:17:02 +08:00 · 6826 次点击
    这是一个创建于 3176 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在写 Java 程序的时候遇到了如下格式的逻辑: if (s instanceof FunctionDef) { ... } else if (s instanceof ClassDef) { ... } else if (s instanceof Return) { ... } ...

    对于这种代码该如何重构才能使得程序看上去更加简洁并且高效?

    20 条回复    2016-04-12 14:28:54 +08:00
    knightdf
        1
    knightdf  
       2016-04-12 09:23:15 +08:00
    换成 Scala 用 match case, 哈哈
    ahmiao
        2
    ahmiao  
       2016-04-12 09:24:15 +08:00   ❤️ 1
    统一接口+子类化?
    wanghaa
        3
    wanghaa  
       2016-04-12 09:31:49 +08:00
    gqlxj1987
        4
    gqlxj1987  
       2016-04-12 09:34:01 +08:00
    工厂+策略模式
    zhuangzhuang1988
        5
    zhuangzhuang1988  
       2016-04-12 09:40:53 +08:00
    import java.util.HashMap;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Map;

    abstract class Validate {
    abstract boolean validate(Object obj);
    abstract void process(Object val);
    }

    class A {

    }
    class B {

    }

    class AValidate extends Validate {

    @Override
    boolean validate(Object obj) {
    return obj instanceof A;
    }

    @Override
    void process(Object val) {
    A a = (A)val;
    // ...
    }
    }

    class BValidate extends Validate {
    @Override
    boolean validate(Object obj) {
    return obj instanceof B;
    }
    @Override
    void process(Object val) {
    B a = (B)val;
    // ...
    }
    }

    public class Main {
    public static void main(String[] args) {
    Object a = new A();
    Validate[] validates = {
    new AValidate(),
    new BValidate()
    };
    for(Validate v: validates ){
    if(v.validate(a)){
    v.process(a);
    break;
    }
    }
    }
    }
    试试下.
    beanlam
        6
    beanlam  
       2016-04-12 09:41:52 +08:00
    用多态,一个分支对应一个实现。这种方法对于有大量分支的情况可能不适用,因为要写大量的类。
    另外一种模式可以参考《代码大全》第十八章提到的“表驱动模式”。
    SpicyCat
        7
    SpicyCat  
       2016-04-12 09:42:57 +08:00
    @ahmiao 同意用接口加子类。 FunctionDef, ClassDef 和 Return 可以实现同一个接口或者继承同一个父类,假设父类叫 Father, 方法名叫 doSomething(), 然后那三个子类各自实现 doSomething(). 这样代码里只需要调用 Father#doSomething 就可以了。
    levn
        8
    levn  
       2016-04-12 09:47:56 +08:00   ❤️ 1
    改成一种更加复杂难懂的方式
    cxshun
        9
    cxshun  
       2016-04-12 09:49:57 +08:00
    面向接口编程,多态就是这个时候用的。
    fwrq41251
        10
    fwrq41251  
       2016-04-12 09:54:58 +08:00
    访问者模式。
    或者用 java8 ,有个叫 javaslang 的类库,有用于类型匹配的类。
    SoloCompany
        11
    SoloCompany  
       2016-04-12 09:56:13 +08:00
    首选是多态
    不适合多态的可以试一下 Kotlin 用 case when 来代替了 if else 而已也没啥区别
    wanttofly
        12
    wanttofly  
       2016-04-12 10:56:59 +08:00
    谢谢回答,最近正好有这方面的修改。
    hrong
        13
    hrong  
       2016-04-12 11:07:10 +08:00 via Android
    @beanlam 表驱动模式对取值还好,要取函数指针就不合适了, JAVA 不支持函数指针,不知道 java8 能否实现
    beanlam
        14
    beanlam  
       2016-04-12 12:21:34 +08:00
    @hrong 是的, jdk1.7 我一般都用匿名内部类作为 value ,伪装函数。
    zhuangzhuang1988
        15
    zhuangzhuang1988  
       2016-04-12 13:37:21 +08:00
    或者看这种解决方式, 当然有点难 `functional-programming-in-scala` 作者写的 http://blog.higher-order.com/blog/2009/08/21/structural-pattern-matching-in-java/
    kaneg
        16
    kaneg  
       2016-04-12 14:02:39 +08:00
    这不就是多态要解决的问题吗
    twoyuan
        17
    twoyuan  
       2016-04-12 14:15:25 +08:00
    我现在是建一个 Map<Class, Callback> map ,用的时候 map.get(object.class)。不过第一次创建时会慢点
    Jaylee
        18
    Jaylee  
       2016-04-12 14:18:29 +08:00
    这应该是用多态吧
    laibin
        19
    laibin  
       2016-04-12 14:24:26 +08:00
    访问者模式。
    haolly
        20
    haolly  
       2016-04-12 14:28:54 +08:00
    重構裏面說過,當你看到大量 switch 或者 if-else 的時候,這表示你應該用多態了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1201 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 17:45 · PVG 01:45 · LAX 09:45 · JFK 12:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.