Java重構-策略模式、狀態模式、衛語句

前言

當代碼中出現多重if-else語句或者switch語句時。弊端之一:若是這樣的代碼出如今多處,那麼一旦出現需求變動,就須要把全部地方的if-else或者switch代碼進行更改,要是遺漏了某一處,那麼程序就會出錯。弊端之二:代碼邏輯難以理解。git

衛語句

衛語句的使用,並不能改變前言說的弊端:一旦需求更改,須要修改全部使用更改需求的if-else代碼塊。不過使用衛語句可讓本身或者代碼維護人員很容易的瞭解代碼的含義。github

代替異常分支

所謂的異常分支就是普通狀況以外的分支,這種狀況的下的if-else能夠用算法

if (condition)
    return obj;

代替。app

代替多重if-else分支

這個狀況的代替方式是能夠爲ide

if (isSunshine()) {
    // 晴天時處理邏輯
}
if (isRain()) {
    // 下雨時處理邏輯
}
if (isOvercast()) {
    // 陰天時處理邏輯
}
...

策略模式

使用策略模式能夠代替多重if-elseswitch語句,讓代碼維護變得更加簡單。
策略模式UML:ui

clipboard.png

  • 環境(Context)角色:持有一個Strategy的引用
  • 抽象策略(Strategy)角色:這是一個抽象角色,一般由一個接口或抽象類實現
  • 具體策略(ConcreteStrategy)角色:包裝了相關的算法或行爲

策略模式代碼模板:this

package xyz.zeling.test.strategy.template;

import xyz.zeling.test.strategy.template.base.Strategy;

/**
 * @description 環境角色
 * @author zeling
 * @date 2018年1月14日 下午8:43:58
 */
public class Context {

    /**
     * 策略對象
     */
    private Strategy strategy;

    /**
     * @param strategy 具體策略對象
     */
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    /**
     * @description 執行策略方法
     * @date 2018年1月14日 下午8:43:31
     */
    public void contextInterface() {
        strategy.strategyInterface();
    }
}
package xyz.zeling.test.strategy.template.base;

/**
 * @description 抽象策略角色
 * @author zeling
 * @date 2018年1月14日 下午8:41:14
 */
public interface Strategy {

    /**
     * @description 策略方法
     * @date 2018年1月14日 下午8:41:00
     */
    void strategyInterface();
}
package xyz.zeling.test.strategy.template;

import xyz.zeling.test.strategy.template.base.Strategy;

/**
 * @description 具體策略類A
 * @author zeling
 * @date 2018年1月14日 下午8:45:00
 */
public class ConcreteStrategyA implements Strategy {

    @Override
    public void strategyInterface() {
        // TODO Auto-generated method stub
    }
}
package xyz.zeling.test.strategy.template;

import xyz.zeling.test.strategy.template.base.Strategy;

/**
 * @description 具體策略類B
 * @author zeling
 * @date 2018年1月14日 下午8:45:00
 */
public class ConcreteStrategyB implements Strategy {

    @Override
    public void strategyInterface() {
        // TODO Auto-generated method stub
    }
}
package xyz.zeling.test.strategy.template;

import xyz.zeling.test.strategy.template.base.Strategy;

/**
 * @description 具體策略類C
 * @author zeling
 * @date 2018年1月14日 下午8:45:00
 */
public class ConcreteStrategyC implements Strategy {

    @Override
    public void strategyInterface() {
        // TODO Auto-generated method stub
    }
}

實例應用:水果有不一樣種類,每種水果對應不一樣價格,用策略模式實現。spa

package xyz.zeling.test.strategy.demo.base;

/**
 * @description 抽象策略,水果接口
 * @author zeling
 * @date 2018年1月14日 下午3:01:20
 */
public interface Fruit {
    /**
     * @description 輸出對應價格
     * @date 2018年1月14日 下午3:03:07
     */
    void price();
}
package xyz.zeling.test.strategy.demo;

import xyz.zeling.test.strategy.demo.base.Fruit;

/**
 * @description 具體策略,蘋果類
 * @author zeling
 * @date 2018年1月14日 下午3:04:17
 */
public class Apple implements Fruit {

    @Override
    public void price() {
        System.out.println("蘋果的價格!");
    }
}
package xyz.zeling.test.strategy.demo;

import xyz.zeling.test.strategy.demo.base.Fruit;

/**
 * @description 具體策略,香蕉
 * @author zeling
 * @date 2018年1月14日 下午3:06:52
 */
public class Banana implements Fruit {

    @Override
    public void price() {
        System.out.println("香蕉的價格!");
    }
}
package xyz.zeling.test.strategy.demo;

import xyz.zeling.test.strategy.demo.base.Fruit;

/**
 * @description 具體策略,梨
 * @author zeling
 * @date 2018年1月14日 下午3:08:19
 */
public class Pear implements Fruit {

    @Override
    public void price() {
        System.out.println("梨的價格!");
    }
}
package xyz.zeling.test.strategy.demo;

import xyz.zeling.test.strategy.demo.base.Fruit;

/**
 * @description 策略環境,輸出水果價格
 * @author zeling
 * @date 2018年1月14日 下午3:09:31
 */
public class FruitPrice {

    /**
     * 策略對象
     */
    private Fruit fruit;

    /**
     * @param fruit 策略對象
     */
    public FruitPrice(Fruit fruit) {
        this.fruit = fruit;
    }
    
    /**
     * @description 輸出水果價格
     * @date 2018年1月14日 下午3:12:26
     */
    public void printFruitPrice() {
        fruit.price();
    }
}

客戶端code

/**
     * @description 使用策略模式:針對一組算法,將每個算法封裝到具備共同接口的獨立的類
     * @date 2018年1月14日 下午3:17:11
     */
    public static void useStrategy() {
        // 具體使用策略
        Fruit apple = new Apple();
        // 將策略放入環境中並執行策略
        new FruitPrice(apple).printFruitPrice();
    }

狀態模式

狀態模式類圖:對象

clipboard.png

說明:

  • 環境(Context)角色,也成上下文:定義客戶端所感興趣的接口,而且保留一個具體狀態類的實例。這個具體狀態類的實例給出此環境對象的現有狀態
  • 抽象狀態(State)角色:定義一個接口,用以封裝環境(Context)對象的一個特定的狀態所對應的行爲
  • 具體狀態(ConcreteState)角色:每個具體狀態類都實現了環境(Context)的一個狀態所對應的行爲

策略模式代碼模板:

package xyz.zeling.test.state.template.base;

/**
 * @description 抽象狀態角色
 * @author zeling
 * @date 2018年1月14日 下午8:41:14
 */
public interface State {

    /**
     * @description 處理方法
     * @date 2018年1月14日 下午8:41:00
     */
    void handle();
}
package xyz.zeling.test.state.template;

import xyz.zeling.test.state.template.base.State;

/**
 * @description 具體狀態類A
 * @author zeling
 * @date 2018年1月14日 下午8:45:00
 */
public class ConcreteStateA implements State {

    @Override
    public void handle() {
        // TODO Auto-generated method stub
    }
}
package xyz.zeling.test.state.template;

import xyz.zeling.test.state.template.base.State;

/**
 * @description 具體狀態類A
 * @author zeling
 * @date 2018年1月14日 下午8:45:00
 */
public class ConcreteStateB implements State {

    @Override
    public void handle() {
        // TODO Auto-generated method stub
    }
}
package xyz.zeling.test.state.template;

import xyz.zeling.test.state.template.base.State;

/**
 * @description 具體狀態類A
 * @author zeling
 * @date 2018年1月14日 下午8:45:00
 */
public class ConcreteStateC implements State {

    @Override
    public void handle() {
        // TODO Auto-generated method stub
    }
}
package xyz.zeling.test.state.template;

import xyz.zeling.test.state.template.base.State;

/**
 * @description 狀態模式,環境角色類
 * @author zeling
 * @date 2018年1月14日 下午8:43:58
 */
public class Context {

    /**
     * 狀態對象
     */
    private State state;

    /**
     * @description 設置狀態
     * @date 2018年1月14日 下午9:13:20
     * @param state 具體狀態
     */
    public void setState(State state) {
        this.state = state;
    }

    /**
     * @description 執行策略方法
     * @date 2018年1月14日 下午8:43:31
     */
    public void request() {
        state.handle();
    }
}

實例應用:橘子有不一樣顏色,狀態不一樣的橘子顏色不一樣,用狀態模式實現。

package xyz.zeling.test.state.demo.base;

/**
 * @description 狀態模式,狀態接口
 * @author zeling
 * @date 2018年1月14日 下午4:13:21
 */
public interface Orange {
    /**
     * @description 輸出橘子的顏色
     * @date 2018年1月14日 下午4:14:00
     */
    void printColor();
}
package xyz.zeling.test.state.demo;

import xyz.zeling.test.state.demo.base.Orange;

/**
 * @description 狀態2:青色的橘子
 * @author zeling
 * @date 2018年1月14日 下午4:17:52
 */
public class CyanOrange implements Orange {

    @Override
    public void printColor() {
        System.out.println("My color is cyan!");
    }
}
package xyz.zeling.test.state.demo;

import xyz.zeling.test.state.demo.base.Orange;

/**
 * @description 橘子狀態管理器
 * @author zeling
 * @date 2018年1月14日 下午4:19:55
 */
public class OrangeStateManage {

    /**
     * 橘子的狀態
     */
    private Orange state;

    /**
     * @description 設置橘子的狀態
     * @date 2018年1月14日 下午4:21:36
     * @param state
     */
    public void setState(Orange state) {
        this.state = state;
    }

    /**
     * @description 輸出當前狀態的橘子顏色
     * @date 2018年1月14日 下午4:22:08
     */
    public void print() {
        state.printColor();
    }
}
package xyz.zeling.test.state.demo;

import xyz.zeling.test.state.demo.base.Orange;

/**
 * @description 狀態1:紅色外觀的橘子
 * @author zeling
 * @date 2018年1月14日 下午4:15:29
 */
public class RedOrange implements Orange {

    @Override
    public void printColor() {
        System.out.println("My color is red!");
    }
}
package xyz.zeling.test.state.demo;

import xyz.zeling.test.state.demo.base.Orange;

/**
 * @description 狀態3:黃色的橘子
 * @author zeling
 * @date 2018年1月14日 下午4:18:45
 */
public class YellowOrange implements Orange {

    @Override
    public void printColor() {
        System.out.println("My color is yellow!");
    }
}

客戶端

/**
     * @description 使用狀態模式:狀態模式,又稱狀態對象模式(Pattern of Objects for
     *              States),狀態模式是對象的行爲模式。狀態模式容許一個對象在其內部狀態改變的時候改變其行爲。這個對象看上去就像是改變了它的類同樣
     * @date 2018年1月14日 下午4:04:16
     */
    public static void useState() {
        // 具體使用狀態
        Orange cyanOrange = new CyanOrange();
        // 建立環境
        OrangeStateManage orangeStateManage = new OrangeStateManage();
        // 設置狀態並執行
        orangeStateManage.setState(cyanOrange);
        orangeStateManage.print();
    }

策略模式和狀態模式的比較

講真,我以爲它們都差很少啊,好難區別啊!!!
不過,雖然講不出來它們的區別是什麼,可是有個例子能夠很好的描述它們的區別

  • 狀態模式:這個模式就比如員工申請離職單的流程,離職單到直接上級,這個狀態就是直接上級批示,等直接上級審閱以後,經過了就到下一個狀態。這一個個狀態對應不一樣的處理,這是有順序要求的。
  • 策略模式:這個模式比如於你假期要出國遊玩,有日本、美國、新加坡等國家,你每到一個國家就執行不一樣的遊玩策略,能夠先去日本,也能夠先去美國,沒有順序要求。

demo

github地址:https://github.com/zeling1005...

相關文章
相關標籤/搜索