【設計模式】策略模式

定義

定義一組算法,將每個算法都封裝起來,並且使它們之間可以互換。【維基百科】

起源

在一個系統中,針對同一種行爲,需要針對不同的情況有各自具體的實現,這時,如果不採用一種比較好的設計模式的話,會出現許多if…else(if)語句,爲了避免這種情況的發生,於是就有了策略模式。

類圖

策略模式類圖
說明

  • Stategy    策略,也就是上文提到的行爲
  • ConcreteStrategy    具體的策略角色,即每一種行爲的具體實現
  • Context    角色,要去執行這些行爲的對象,在這個類中,會將抽象的行爲注入進去,即Stategy,在執行行爲的時候,會根據具體的子類對象去執行對應的行爲。

case

員工每天早上去上班,不同的人,上班的時間點和採用的交通方式也不一樣,住的遠的人,7點就要出發了,坐公交或者自駕,住的近的人,可能7點30分纔出發,騎自行車或者電動車,如果在沒有使用策略模式之前,代碼是這樣實現的:

package com.steven.cn.simple;

public class Test1 {
	
	/**
	 * 枚舉,爲了測試方便
	 * @author Steven
	 *
	 */
	private enum Type {
		FAR("FAR", "住的遠的人"), NEAR("NEAR", "住的近的人");
		private String value;
		private String valueName;
		private Type(String value, String valueName) {
			this.value = value;
			this.valueName = valueName;
		}
	}
	
	/**
	 * 行爲
	 * @param type
	 */
	public static void goCompany(String type) {
		if(Type.FAR.value.equals(type)) {
			System.out.println("每天7點鐘從家出發,坐公交或者自駕");
		}else if(Type.NEAR.value.equals(type)) {
			System.out.println("每天7點30分從家出發,騎自行車或者電動車");
		}
	}

	public static void main(String[] args) {
		goCompany(Type.FAR.value);
	}
}

如果採用策略模式的話,會變成下面這種方式:
首先會有一個抽象的行爲類,一般是採用接口,可以多實現

package com.steven.cn.stategy;

/**
 * 策略類
 * @author Steven
 *
 */
public interface IStategy {

	public void goCompany();
}

行爲的具體實現,因爲有不同的實現方式,所以會有多個類

package com.steven.cn.stategy.impl;

import com.steven.cn.stategy.IStategy;

/**
 * 住的遠的人的行爲實現類
 * @author Steven
 *
 */
public class ConcreteStrategyA implements IStategy{

	@Override
	public void goCompany() {
		System.out.println("每天7點鐘從家出發,坐公交或者自駕");
	}

}
package com.steven.cn.stategy.impl;

import com.steven.cn.stategy.IStategy;

/**
 * 住的近的人的行爲實現類
 * @author Steven
 *
 */
public class ConcreteStrategyB implements IStategy{

	@Override
	public void goCompany() {
		System.out.println("每天7點30分從家出發,騎自行車或者電動車");
	}

}

最後會有一個角色類,這個類會決定行爲的具體實現方式

package com.steven.cn.context;

import com.steven.cn.stategy.IStategy;

public class Employee {

	private IStategy stategy;

	public Employee(IStategy stategy) {
		this.stategy = stategy;
	}
	
	public IStategy getStategy() {
		return stategy;
	}

    // 這裏提供set方法,是爲了多一種方式封裝角色,可以只使用構造方法來封裝角色。
	public void setStategy(IStategy stategy) {
		this.stategy = stategy;
	}

	public void execGoCompany() {
		stategy.goCompany();
	}
}

測試類

package com.steven.cn;

import com.steven.cn.context.Employee;
import com.steven.cn.stategy.impl.ConcreteStrategyA;
import com.steven.cn.stategy.impl.ConcreteStrategyB;

public class Test {

	public static void main(String[] args) {
		Employee employee;
		
		// 住的遠的人
		employee = new Employee(new ConcreteStrategyA());
		employee.execGoCompany();
		System.out.println("--------------");
		// 住的近的人
		employee = new Employee(new ConcreteStrategyB());
		employee.execGoCompany();
		System.out.println("--------------");
		
		employee.setStategy(new ConcreteStrategyA());
		employee.execGoCompany();
		System.out.println("--------------");
	}
}

最後的輸出結果是

結果自己運行一下就知道了。。。

END

通過上面兩種情況下代碼的對比,優缺點很明顯了

優點:
  1. 避免使用繁雜的if...else(if)語句進行判斷
  2. 行爲的具體實現方式可以自由的切換,通過封裝不同的角色就可以實現不同的行爲
  3. 擴展性高,增加一種行爲的實現方式,只需要實現接口即可
缺點
  1. 類增多了,每添加一個行爲的具體實現,就多出一個類出來
  2. 所有的實現方式都必須告訴別人,這樣別人才能決定使用哪個策略角色

源碼下載地址:源碼下載地址
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章