策略模式主要针对一些拓展性特别强的方法进行类封装
今天就来学透策略模式
策略模式的定义
该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
策略模式举例了解
策略模式主要分三步(人陪猫玩):
人和猫是对象,玩是方法。方法有很多种,可以定义多个方法,在调用时写上具体的调用方法;但是这样在维护时会修改代码,违反开闭原则。同时,在大量的不同的行为方式也会导致类的类的体积庞大。此时就可以考虑使用策略模式:
第一步:找到要进行封装的方法
定义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();
}
实现具体的策略
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("我红外线逗猫玩");
}
}
第二步:调用策略接口,准备利用多态,实现不同的具体策略
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.直接在需要调用的地方new 出从刚才创建的策略行为 注意:此时的策略模式使用单例因为策略模式知识针对行为的模式,在这里单例更为合适
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());
}
/**
* 构造方法私有化
*/
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.对于经常会发生变化的策略 我们还可以将所有策略写在配置类中,这样更加灵活,同样也是需要将每个策略模式携程单例模式。
读取配置文件类
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);
//将类加载到内存中(利用无参构造的方式)
PlayWithCatStrategy playWithCatStrategy = (PlayWithCatStrategy)Class.forName(name).getDeclaredConstructor().newInstance();
person.playWithCat(playWithCatStrategy);
}
}
最后,策略模式基本限于明显需要很强的拓展性的地方,例如像微信的消息处理、设备的读取数据....等这类需要明显在后期开发中进行拓展时,我们选择策略模式是比较好的