策略模式 |
- 策略模式:也叫作政策模式,定義一組算法,將每個算法都封裝起來,並且使他們之間可以互換
- 策略模式的使用就是面向對象的繼承和多態機制,其通用類圖如下:
-
- Context封裝角色,也叫作上下文角色,屏蔽高層模塊對策略、算法的直接訪問,封裝可能的變化。
- Istrategy抽象策略角色,策略算法家族的抽象,通常為接口定義每個算法必須具有的方法和屬性。
- ConcreteStrategy具體策略角色,實現抽象策略中的操作該類含有具體的算法。
通用類圖的源碼如下:
-
-
public interface IStrategy { //定義具體策略必須具有的方法 public void doSomething(); } public class ConcreteStrategy1 implements IStrategy{ public void doSomething(){ System.out.println("this is a concreteStrategy"); } } public class ConcreteStrategy2 implements IStrategy{ @Override public void doSomething() { // TODO Auto-generated method stub System.out.println("This is concreteStrategy2"); } } public class Context { private IStrategy strategy = null; public Context(IStrategy strategy){ this.strategy = strategy; } public void doSomething(){ this.strategy.doSomething(); } } public class Client { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Context text = new Context(new ConcreteStrategy2()); text.doSomething(); text = new Context(new ConcreteStrategy1()); text.doSomething(); } }
-
策略模式的優缺點 |
- 策略模式的優點
- 算法可以自由的切換,通過實現抽象策略,通過封裝角色對其封裝,保證對外提供“可自由切換”的策略。
- 避免使用多重條件判斷,如果有多重策略,那么每個策略只需實現自己的方法,至於采用何種策略,可以通過其他模塊決定。
- 擴展性良好,可以在現有的系統中任意的加入新的策略,只需繼承IStrategy接口,符合OCP原則。
- 策略模式的缺點
- 策略類數量增多,每個策略都是一個類,復用的可能性很小,類數量增多
- 所有的策略都需要對外暴露,上層模塊必須知道有哪些策略,然后才能知道采用哪種策略,可以通過使用工廠方法模式、代理模式和享元模式修正。
策略模式的擴展(工廠方法模式+策略模式) |
首先策略枚舉StrategyMan,負責對具體策略的映射,然后建立一個簡單的工廠,根據策略管理類的枚舉項創建一個策略對象,簡單而實用,策略模式的缺陷得到了彌補。其通用類圖如下:
-
public enum StrategyMan { Strategy1("com.strategy.ConcreteStrategy1"), Strategy2("com.strategy.ConcreteStrategy2"); String value = ""; private StrategyMan(String value){ this.value = value; } public String getValue(){ return this.value; } } public class StrategyFactory { public static IStrategy getStrategy(StrategyMan strategyman){ IStrategy strategy = null; try { strategy = (IStrategy) Class.forName(strategyman.getValue()).newInstance(); } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return strategy; } } public class StrategyFacade { public void doSomething(String str){ StrategyMan sMan = null; if(str.equalsIgnoreCase("Strategy1")){ sMan = StrategyMan.Strategy1; }else if(str.equalsIgnoreCase("Strategy2")){ sMan = StrategyMan.Strategy2; } IStrategy strategy = StrategyFactory.getStrategy(sMan); Context context = new Context(strategy); context.doSomething(); } } public class Client { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub StrategyFacade sFacade = new StrategyFacade(); sFacade.doSomething("Strategy1"); } }