Dealing with nested if then else/nested switch statements

前端 未结 7 1559
走了就别回头了
走了就别回头了 2020-12-30 08:43

Are there any design patterns/methods/ways to remove nested if then else conditions/switch statements?

I remember coming across some methods used by the Google folks

7条回答
  •  长发绾君心
    2020-12-30 09:06

    You don't say what language you're using, but if you are using an OO language such as C++, C# or Java, you can often use virtual functions to solve the same problem as you are currently solving with a switch statement, and in a more extensible way. In the case of C++, compare:

    class X {
    public:
        int get_type();     /* Or an enum return type or similar */
        ...
    };
    
    void eat(X& x) {
        switch (x.get_type()) {
        TYPE_A: eat_A(x); break;
        TYPE_B: eat_B(x); break;
        TYPE_C: eat_C(x); break;
        }
    }
    
    void drink(X& x) {
        switch (x.get_type()) {
        TYPE_A: drink_A(x); break;
        TYPE_B: drink_B(x); break;
        TYPE_C: drink_C(x); break;
        }
    }
    
    void be_merry(X& x) {
        switch (x.get_type()) {
        TYPE_A: be_merry_A(x); break;
        TYPE_B: be_merry_B(x); break;
        TYPE_C: be_merry_C(x); break;
        }
    }
    

    with

    class Base {
        virtual void eat() = 0;
        virtual void drink() = 0;
        virtual void be_merry() = 0;
        ...
    };
    
    class A : public Base {
    public:
        virtual void eat() { /* Eat A-specific stuff */ }
        virtual void drink() { /* Drink A-specific stuff */ }
        virtual void be_merry() { /* Be merry in an A-specific way */ }
    };
    
    class B : public Base {
    public:
        virtual void eat() { /* Eat B-specific stuff */ }
        virtual void drink() { /* Drink B-specific stuff */ }
        virtual void be_merry() { /* Be merry in an B-specific way */ }
    };
    
    class C : public Base {
    public:
        virtual void eat() { /* Eat C-specific stuff */ }
        virtual void drink() { /* Drink C-specific stuff */ }
        virtual void be_merry() { /* Be merry in a C-specific way */ }
    };
    

    The advantage is that you can add new Base-derived classes D, E, F and so on without having to touch any code that only deals with pointers or references to Base, so there is nothing that can get out of date the way that a switch statement can in the original solution. (The transformation looks very similar in Java, where methods are virtual by default, and I'm sure it looks similar in C# too.) On a large project, this is a huge maintainability win.

提交回复
热议问题