02设计模式之策略模式

策略模式主要针对一些拓展性特别强的方法进行类封装

今天就来学透策略模式

策略模式的定义

该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

策略模式举例了解

策略模式主要分三步(人陪猫玩):

人和猫是对象,玩是方法。方法有很多种,可以定义多个方法,在调用时写上具体的调用方法;但是这样在维护时会修改代码,违反开闭原则。同时,在大量的不同的行为方式也会导致类的类的体积庞大。此时就可以考虑使用策略模式:

第一步:找到要进行封装的方法

定义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);
    }
}

最后,策略模式基本限于明显需要很强的拓展性的地方,例如像微信的消息处理、设备的读取数据....等这类需要明显在后期开发中进行拓展时,我们选择策略模式是比较好的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言 策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可...
    萨达哈鲁酱阅读 257评论 0 1
  • 设计模式之策略模式 1.意图 根据GOF的定义:定义一系列的算法或操作,并把它们一个个封装起来,并且使它们可以互换...
    dandan的微笑阅读 615评论 0 0
  • 在程序设计中,我们也常常遇到类似的情况,要实现某一个功能有多种方案可以选择。比如一个压缩文件的程序,既可以选择zi...
    yufawu阅读 388评论 0 3
  • 一个阳光明媚的上午,靓仔正在开心的划水摸鱼,耳机里传来音乐“不是吧不是吧,难道单压也算压......” 产品经理突...
    靓仔聊编程阅读 332评论 0 3
  • 1. 介绍 策略模式定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到客户端。从概...
    天羽天阅读 316评论 0 0