策略模式主要針對一些拓展性特別強的方法進行類封裝
今天就來學透策略模式
策略模式的定義
該模式定義了一系列算法勤庐,并將每個算法封裝起來拐格,使它們可以相互替換百拓,且算法的變化不會影響使用算法的客戶渠鸽。策略模式屬于對象行為模式嫂粟,它通過對算法進行封裝读虏,把使用算法的責任和算法的實現(xiàn)分割開來责静,并委派給不同的對象對這些算法進行管理。
策略模式舉例了解
策略模式主要分三步(人陪貓玩):
人和貓是對象盖桥,玩是方法灾螃。方法有很多種,可以定義多個方法揩徊,在調(diào)用時寫上具體的調(diào)用方法腰鬼;但是這樣在維護時會修改代碼,違反開閉原則塑荒。同時熄赡,在大量的不同的行為方式也會導(dǎo)致類的類的體積龐大。此時就可以考慮使用策略模式:
第一步:找到要進行封裝的方法
定義Person類
package com.wwj.strategymode;
/**
* 人
*/
public class Person {
private String name;
/**
* 人與貓玩
*/
public void playWithCat(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
抽象玩耍行為為策略接口
package com.wwj.strategymode;
/**
* 人陪貓玩耍策略接口
*/
public interface PlayWithCatStrategy {
/**
* 人與貓玩耍
*/
void play();
}
實現(xiàn)具體的策略
package com.wwj.strategymode;
/**
* 用逗貓棒陪貓玩耍
*/
public class StickPlayWithCatStrategy implements PlayWithCatStrategy{
@Override
public void play() {
System.out.println("我逗貓棒逗貓玩");
}
}
package com.wwj.strategymode;
/**
* 用紅外線陪貓玩耍
*/
public class InfraredPlayWithCatStrategy implements PlayWithCatStrategy{
@Override
public void play() {
System.out.println("我紅外線逗貓玩");
}
}
第二步:調(diào)用策略接口齿税,準備利用多態(tài)彼硫,實現(xiàn)不同的具體策略
package com.wwj.strategymode;
/**
* 人
*/
public class Person {
private String name;
/**
* 人與貓玩
*/
public void playWithCat(PlayWithCatStrategy playWithCatStrategy){
playWithCatStrategy.play();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
第三步:***最后使用策略模式(三種方式)
1.直接在需要調(diào)用的地方new 出從剛才創(chuàng)建的策略行為 注意:此時的策略模式使用單例因為策略模式知識針對行為的模式,在這里單例更為合適
package com.wwj.strategymode;
public class main {
public static void main(String[] args) {
Person person = new Person();
person.setName("張三");
PlayWithCatStrategy playWithCatStrategy;
String key = "0";
if ("0".equals(key)){
playWithCatStrategy = new InfraredPlayWithCatStrategy();
}else{
playWithCatStrategy = new StickPlayWithCatStrategy();
}
person.playWithCat(playWithCatStrategy);
}
}
2.有的時候直接new出行為還需要寫很多層if esle,這是我們就可以采用將所有的策略在java的配置類中進行將全部策略初始化拧篮,利用map去避免ifelse的判斷词渤,這樣在使用時只需要修改配置類中的初始化方法和新增策略類就可以進行拓展
package com.wwj.strategymode;
import java.util.HashMap;
import java.util.Map;
/**
* 策略模式的配置類
*/
public class PlayStrtegyConfig {
public static final Map<String,Object> map = new HashMap<>();
static {
map.put("0",new StickPlayWithCatStrategy());
map.put("1",new InfraredPlayWithCatStrategy());
}
/**
* 構(gòu)造方法私有化
*/
private PlayStrtegyConfig(){}
}
package com.wwj.strategymode;
public class main {
public static void main(String[] args) {
Person person = new Person();
person.setName("張三");
String key = "1";
PlayWithCatStrategy playWithCatStrategy = (PlayWithCatStrategy)PlayStrtegyConfig.map.get(key);
person.playWithCat(playWithCatStrategy);
}
}
3.對于經(jīng)常會發(fā)生變化的策略 我們還可以將所有策略寫在配置類中,這樣更加靈活串绩,同樣也是需要將每個策略模式攜程單例模式缺虐。
讀取配置文件類
package com.wwj.strategymode;
import com.wwj.tank.ConfigMgr;
import java.io.IOException;
import java.util.Properties;
/**
* 獲取配置文件信息(單例)
*/
public class PlayStrtegyConfigFile {
private static final PlayStrtegyConfigFile instance = new PlayStrtegyConfigFile();
private static Properties prop = new Properties();
static {
try {
prop.load(ConfigMgr.class.getClassLoader().getResourceAsStream("config.properties"));
} catch (IOException e) {
e.printStackTrace();
}
}
private PlayStrtegyConfigFile(){}
public static PlayStrtegyConfigFile getInstance(){
return instance;
}
public String get(String name){
if(prop == null) return null;
return prop.get(name).toString();
}
}
配置文件
#玩的策略
0=com.wwj.strategymode.InfraredPlayWithCatStrategy
1=com.wwj.strategymode.StickPlayWithCatStrategy
利用Class類加載對象
package com.wwj.strategymode;
import java.lang.reflect.InvocationTargetException;
public class main {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Person person = new Person();
person.setName("張三");
String key = "1";
//獲取配置文件的類型
String name = PlayStrtegyConfigFile.getInstance().get(key);
//將類加載到內(nèi)存中(利用無參構(gòu)造的方式)
PlayWithCatStrategy playWithCatStrategy = (PlayWithCatStrategy)Class.forName(name).getDeclaredConstructor().newInstance();
person.playWithCat(playWithCatStrategy);
}
}
最后,策略模式基本限于明顯需要很強的拓展性的地方礁凡,例如像微信的消息處理高氮、設(shè)備的讀取數(shù)據(jù)....等這類需要明顯在后期開發(fā)中進行拓展時,我們選擇策略模式是比較好的