在日常开发中,常常会作一些状态判断,用到 swich-case if-else 。在面向对象的环境里,有两种方式可以替代它们。一种是使用继承子类的多态,另一种是使用 state 模式。它们使用对象的间接性有效地摆脱了传统的状态判断。
举个例子。
Method.java

package com.zj.original;

 

import com.zj.utils.NoMethodTypeException;

 

public class Method {

    private int _type ;

    public static final int POST = 0;

    public static final int GET = 1;

    public static final int PUT = 2;

    public static final int DELETE = 3;

 

    public Method( int type) {

       _type = type;

    }

 

    public String getMethod() throws NoMethodTypeException {

       switch ( _type ) {

       case POST :

           return "This is POST method" ;

       case GET :

           return "This is GET method" ;

       case PUT :

           return "This is PUT method" ;

       case DELETE :

           return "This is DELETE method" ;

       default :

           throw new NoMethodTypeException();

       }

    }

 

    public boolean safeMethod() {

       if ( _type == GET )

           return true ;

       else

           return false ;

    }

 

    public boolean passwordRequired() {

       if ( _type == POST )

           return false ;

       else

           return true ;

    }

}

Method 中,存在四个状态 Post Get Put Delete 。有一个 switch-case 判断,用于输出四种方法的描述信息;两个 if-else 判断,分别判断方法是否安全 ( 只有 Get 方法是安全的 ) ,方法是否需要密码 ( 只有 Post 方法不需要密码 )

 

1. 使用继承子类多态

使用继承子类多态的方式,通常对于某个具体对象,它的状态是不可改变的 ( 在对象的生存周期中 )

现在使用四个子类分别代表四种类型的方法。这样就可以使用多态将各个方法的具体逻辑分置到子类中去了。
在抽象基类 Method 中可以提供创建子类实例的静态方法,当然也可以使用 Simple Factory 模式。对于 getMethod() 方法,延迟到子类中实现;对于 safeMethod() 方法和 passwordRequired() 方法,提供一个默认的实现,这个实现应该符合绝大部分子类的要求,这样的话,对于少数不符合默认实现的子类只需 override 相应方法即可。
<<abstract>>Method.java

package com.zj.subclass;

 

public abstract class Method {

 

    public final static Method createPostMethod() {

       return new PostMethod();

    }

 

    public final static Method createGetMethod() {

       return new GetMethod();

    }

 

    public final static Method createPutMethod() {

       return new PutMethod();

    }

 

    public final static Method createDeleteMethod() {

       return new DelMethod();

    }

 

    abstract public String getMethod();

 

    public boolean safeMethod() {

       return false ;

    }

 

    public boolean passwordRequired() {

       return true ;

    }

}
四个子类分别继承和 override 相应的方法。
PostMethod.java

package com.zj.subclass;

 

public class PostMethod extends Method {

    @Override

    public String getMethod() {

       return "This is POST method" ;

    }

 

    @Override

    public boolean passwordRequired() {

       return false ;

    }

}
GetMethod.java

package com.zj.subclass;

 

public class GetMethod extends Method{

    @Override

    public String getMethod() {

       return "This is GET method" ;

    }

 

    @Override

    public boolean safeMethod() {

       return true ;

    }

}
PutMethod.java

package com.zj.subclass;

 

public class PutMethod extends Method {

    @Override

    public String getMethod() {

       return "This is PUT method" ;

    }

}

DelMethod.java

package com.zj.subclass;

 

public class DelMethod extends Method{

    @Override

    public String getMethod(){

       return "This is DELETE method" ;

    }

}
2. 使用 state 模式

如果希望对象在生存周期内,可以变化自己的状态,则可以选择 state 模式。

这里抽象状态为一个接口 MethodType ,四种不同的状态实现该接口。
<<interface>>MethodType.java

package com.zj.state;

 

public interface MethodType {

    String getTypeDescription();

 

    String getMethodDescription();

 

    boolean isSafe();

 

    boolean isRequired();

}
Post.java

package com.zj.state;

 

public class Post implements MethodType{

    public String getMethodDescription() {

       return "This is POST method" ;

    }

 

    public String getTypeDescription() {

       return "===POST===" ;

    }

 

    public boolean isRequired() {

       return false ;

    }

 

    public boolean isSafe() {

       return false ;

    }

}
Get.java

package com.zj.state;

 

public class Get implements MethodType{

    public String getMethodDescription() {

       return "This is GET method" ;

    }

 

    public String getTypeDescription() {

       return "===GET===" ;

    }

 

    public boolean isRequired() {

       return true ;

    }

 

    public boolean isSafe() {

       return true ;

    }

}

Put.java

package com.zj.state;

 

public class Put implements MethodType{

    public String getMethodDescription() {

       return "This is PUT method" ;

    }

 

    public String getTypeDescription() {

       return "===PUT===" ;

    }

 

    public boolean isRequired() {

       return true ;

    }

 

    public boolean isSafe() {

       return false ;

    }

}

Delete.java

package com.zj.state;

 

public class Delete implements MethodType{

    public String getMethodDescription() {

       return "This is DELETE method" ;

    }

 

    public String getTypeDescription() {

       return "===DELETE===" ;

    }

 

    public boolean isRequired() {

       return true ;

    }

 

    public boolean isSafe() {

       return false ;

    }

}
此时,在类 Method 中保存一个 field 表示 MethodType ,在某对象中,可以随时变化四种已知的状态 ( 具体见 runAllMethods() 方法 )
Method.java

package com.zj.state;

 

public class Method {

    private MethodType _type ;

 

    public Method() {

       _type = null ;

    }

 

    public Method(MethodType type) {

       _type = type;

    }

 

    public String getMethod() {

       return _type .getMethodDescription();

    }

 

    public boolean safeMethod() {

       return _type .isSafe();

    }

 

    public boolean passwordRequired() {

       return _type .isRequired();

    }

 

    public void changeType(MethodType type) {

       _type = type;

    }

 

    public void runAllMethods() {

       MethodType[] types = new MethodType[] { new Post(), new Get(),

              new Put(), new Delete() };

       for (MethodType type : types) {

           System. out .println(type.getTypeDescription());

           changeType(type);

           System. out .println(getMethod());

           System. out .println(safeMethod());

           System. out .println(passwordRequired());

       }

    }

}
3.测试

在测试类中,分别使用上面 3 中机制展示结果。它们的结果应该是一致的。
Client.java

package com.zj.utils;

 

public class Client {

    static void print(String s) {

       System. out .println(s);

    }

 

    static void print(Boolean b) {

       System. out .println(b);

    }

 

    public static void main(String[] args) throws NoMethodTypeException {

       print( "===original===" );

       print( "===POST===" );

       com.zj.original.Method post1 = new com.zj.original.Method(

              com.zj.original.Method. POST );

       print(post1.getMethod());

       print(post1.safeMethod());

       print(post1.passwordRequired());

       print( "===GET===" );

       com.zj.original.Method get1 = new com.zj.original.Method(

              com.zj.original.Method. GET );

       print(get1.getMethod());

       print(get1.safeMethod());

       print(get1.passwordRequired());

       print( "===PUT===" );

       com.zj.original.Method put1 = new com.zj.original.Method(

              com.zj.original.Method. PUT );

       print(put1.getMethod());

       print(put1.safeMethod());

       print(put1.passwordRequired());

       print( "===DELETE===" );

       com.zj.original.Method del1 = new com.zj.original.Method(

              com.zj.original.Method. DELETE );

       print(del1.getMethod());

       print(del1.safeMethod());

       print(del1.passwordRequired());

 

       print( "===subclass===" );

       print( "===POST===" );

       com.zj.subclass.Method post2 = com.zj.subclass.Method

              .createPostMethod();

       print(post2.getMethod());

       print(post2.safeMethod());

       print(post2.passwordRequired());

       print( "===GET===" );

       com.zj.subclass.Method get2 = com.zj.subclass.Method.createGetMethod();

       print(get2.getMethod());

       print(get2.safeMethod());

       print(get2.passwordRequired());

       print( "===PUT===" );

       com.zj.subclass.Method put2 = com.zj.subclass.Method.createPutMethod();

       print(put2.getMethod());

       print(put2.safeMethod());

       print(put2.passwordRequired());

       print( "===DELETE===" );

       com.zj.subclass.Method del2 = com.zj.subclass.Method

              .createDeleteMethod();

       print(del2.getMethod());

       print(del2.safeMethod());

       print(del2.passwordRequired());

 

        print( "===state===" );

       new com.zj.state.Method().runAllMethods();

    }

}