Java中的条件分支

Java中的条件分支,java,if-statement,switch-statement,Java,If Statement,Switch Statement,我想知道你认为哪一个设计更好。如果我们有 /* * Created 21 Feb 2014 */ import java.util.Properties; import java.util.Random; /** * * @author me */ enum EventType{ TRADE, RISK, SHIPPING, MARGIN, STOP_LOSS, TAKE_PROFIT } interface Event{ EventType getType();

我想知道你认为哪一个设计更好。如果我们有

/*
* Created 21 Feb 2014
*/


import java.util.Properties;
import java.util.Random;

/**
*
* @author me
*/

enum EventType{
    TRADE, RISK, SHIPPING, MARGIN, STOP_LOSS, TAKE_PROFIT
}

interface Event{
    EventType getType();
    Properties getProperties();
}


class ShippingEvent implements Event{
    public final static String PROPERTY_KEY1 = "property_ke1";
    public final static String PROPERTY_KEY2 = "property_ke2";
    public final static String PROPERTY_KEY3 = "property_ke3";

    @Override
    public EventType getType() {
        return EventType.SHIPPING;
    }

    @Override
    public Properties getProperties() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}


class TradeEvent implements Event{
    public final static String PROPERTY_KEY1 = "property_ke1";
    public final static String PROPERTY_KEY2 = "property_ke2";
    public final static String PROPERTY_KEY3 = "property_ke3";

    @Override
    public EventType getType() {
        return EventType.TRADE;
    }

    @Override
    public Properties getProperties() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

class RiskEvent implements Event{
    public final static String PROPERTY_KEY1 = "property_ke1";
    public final static String PROPERTY_KEY2 = "property_ke2";
    public final static String PROPERTY_KEY3 = "property_ke3";

    @Override
    public EventType getType() {
        return EventType.RISK;
    }

    @Override
    public Properties getProperties() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

class MarginEvent implements Event{
    public final static String PROPERTY_KEY1 = "property_ke1";
    public final static String PROPERTY_KEY2 = "property_ke2";
    public final static String PROPERTY_KEY3 = "property_ke3";

    @Override
    public EventType getType() {
        return EventType.MARGIN;
    }

    @Override
    public Properties getProperties() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

class StopLossEvent implements Event{
    public final static String PROPERTY_KEY1 = "property_ke1";
    public final static String PROPERTY_KEY2 = "property_ke2";
    public final static String PROPERTY_KEY3 = "property_ke3";

    @Override
    public EventType getType() {
        return EventType.STOP_LOSS;
    }

    @Override
    public Properties getProperties() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

class TakeProfiEvent implements Event{
    public final static String PROPERTY_KEY1 = "property_ke1";
    public final static String PROPERTY_KEY2 = "property_ke2";
    public final static String PROPERTY_KEY3 = "property_ke3";

    @Override
    public EventType getType() {
        return EventType.TAKE_PROFIT;
    }

    @Override
    public Properties getProperties() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

public class InstanceOfTest {

    private static void testIfBranch(final Event event){
        if (event instanceof TakeProfiEvent){
            System.out.println("TakeProfiEvent");
        }else if (event instanceof StopLossEvent){
            System.out.println("StopLossEvent");
        }else if (event instanceof MarginEvent){
            System.out.println("MarginEvent");
        }else if (event instanceof RiskEvent){
            System.out.println("RiskEvent");
        }else if (event instanceof TradeEvent){
            System.out.println("TradeEvent");
        }else if (event instanceof ShippingEvent){
            System.out.println("ShippingEvent");
        }
    }




    private static void testSwitchBranch(final Event event){

        switch(event.getType()){
            case TRADE:
                System.out.println("TradeEvent");
                break;
            case RISK:
                System.out.println("RiskEvent");
                break;
            case SHIPPING:
                System.out.println("ShippingEvent");
                break;
            case MARGIN:
                System.out.println("MarginEvent");
                break;
            case STOP_LOSS:
                System.out.println("StopLossEvent");
                break;
            case TAKE_PROFIT:
                System.out.println("TakeProfiEvent");    
                break;
            default:
                break;
        }
    }

    public static void main(String[] args){
        Event[] events = new Event[] {
            new TakeProfiEvent(),
            new StopLossEvent(),
            new MarginEvent(),
            new RiskEvent(),
            new TradeEvent(),
            new ShippingEvent()
        };


        Random random = new Random(System.currentTimeMillis());
        long start = System.currentTimeMillis();
        for(int idx=0; idx<10000000; ++idx){
            int jdx = random.nextInt(events.length-1);
            //testIfBranch(events[jdx]);
            testSwitchBranch(events[jdx]);
        }
        long end = System.currentTimeMillis();

        System.out.println("Time taken: " + (end - start));
    }

}

就我从剥离的示例中所见,这两种方法在软件工程方面都不是真正的可扩展和易于维护的

重要的问题是:您在实际应用程序中如何处理这些事件(及其类型)?即:是否确实需要查询类型

在这种情况下,至少应该考虑的一般模式是用某种多态性隐藏类型查询。要以过于暗示的形式指出这一点:

interface Event{
    void performAction();
    Properties getProperties();
}

class ShippingEvent implements Event{
    @Override
    public void performAction() {
        // Whatever you would otherwise do based on the event type:
        System.out.println("ShippingEvent");
    }
    ....
}


private static void testPolymorphism(final Event event){ 
    event.performAction(); // That's it. No type queries here.
}

但是从发布的代码中很难判断这是否(以及如何)适用于您的情况……

就我从剥离的示例中所看到的情况而言,从软件工程的角度来看,这两种方法都不是真正可扩展且易于维护的

重要的问题是:您在实际应用程序中如何处理这些事件(及其类型)?即:是否确实需要查询类型

在这种情况下,至少应该考虑的一般模式是用某种多态性隐藏类型查询。要以过于暗示的形式指出这一点:

interface Event{
    void performAction();
    Properties getProperties();
}

class ShippingEvent implements Event{
    @Override
    public void performAction() {
        // Whatever you would otherwise do based on the event type:
        System.out.println("ShippingEvent");
    }
    ....
}


private static void testPolymorphism(final Event event){ 
    event.performAction(); // That's it. No type queries here.
}

但是这是否(以及如何)适用于您的情况,很难从发布的代码中判断…

最好的设计无疑是开关式的。有关最佳实践,请参阅
最好的设计无疑是开关式的。有关最佳实践,请参阅
本例中的性能参数与if vs switch没有多大关系,因为您在它们中做的事情不同。您的if正在测试类是否属于特定类型,而您的交换机正在检查枚举相等性

此外,在设计方面,你提供的信息很少,所以很难对什么更好做出任何判断。如果您提供了一些信息,说明为什么要做这些条件语句,以及您希望在每个分支上做些什么,这将是使讨论变得更好的良好的第一步


就最佳实践而言,您希望避免如此长的if/else构造或switch语句,并根据您的情况采用多态性之类的解决方案。

本例中的性能参数与if vs switch没有太多关系,因为您在它们中做的事情不同。您的if正在测试类是否属于特定类型,而您的交换机正在检查枚举相等性

此外,在设计方面,你提供的信息很少,所以很难对什么更好做出任何判断。如果您提供了一些信息,说明为什么要做这些条件语句,以及您希望在每个分支上做些什么,这将是使讨论变得更好的良好的第一步


就最佳实践而言,您希望避免如此长的if/else构造或switch语句,并根据您的情况采用多态性等解决方案。

两者之间的性能差异可以忽略不计;选择一个更容易理解和管理的开关(无论如何看起来像
开关
变体)。枚举开关通常编译为一个O(1)
表开关
,除非您只有一个带有稀疏序数的枚举值子集的案例,在这种情况下,您可能会得到一个O(logn)
查找开关
(但大多数编译器将保证使用
表开关
)。无论哪种方式,它都比O(n)直链的
if/else if
语句要好。两者之间的性能差异可以忽略不计;选择一个更易于理解和管理的开关(不管怎样,它看起来像
开关
变体).enum开关通常编译为O(1)
表开关
,除非只有带有稀疏序数的enum值子集的case,在这种情况下,您可能会得到一个O(logn)
查找开关
(但大多数编译器将保证
表开关
)。无论哪种方式,它都比O(n)好
if/else if
语句的直链。本文没有提出
开关
解决方案(而是提出多态性,如我在中所述)诚然,我没有解释代码的目的,只是比较了两种方法。为了更彻底一点,如果事件部分以Swing为中心,我建议阅读优秀的java事件。我还建议检查。希望我能提供一些帮助!本文没有提出
开关
解决方案(相反,它提出了多态性,正如我在中提到的)是的,我没有解释代码的目的,只是比较了两种方法。为了更彻底一点,如果事件部分以Swing为中心,我建议阅读优秀java事件。我还建议检查。希望我能提供一些帮助!不能更同意你。不能更同意你。