设计模式之:策略模式,解决if...else,以及switch..case

设计模式中的六大原则:

       1、单一职责原则(Single Responsibility Principle,简称SRP )

       2、里氏替换原则(Liskov Substitution Principle,简称LSP)

       3、依赖倒置原则(Dependence Inversion Principle,简称DIP)

       4、接口隔离原则(Interface Segregation Principle,简称ISP)

       5、迪米特法则(Law of Demeter,简称LoD)

       6、开放封闭原则(Open Close Principle,简称OCP)

      在23中设计模式中,策略模式相对来说,还是很实用的,一般我们会碰到各种的if...else,或者switch..case,写这个时候一般情况下可以会写很多层的if..else,或者switch..case。这样写法能实现基本功能,但是如果碰到需要添加就很痛苦了,比如例子:

public void judgmentType(String type) {
        switch (type) {
        case "1500":
            System.out.println("");
            break;
        case "1888":
            System.out.println("");
            break;
        case "2100":
            System.out.println("");
            break;
        case "5100":
            System.out.println("");
            break;
        case "2200":
            System.out.println("");
            break;
        case "2280":
            System.out.println("");
            break;
        default:
            break;
        }
    }

这种情况下,如果要添加业务,就得继续添加switch..case,非常不灵活。所以我们通过策略模式来实现对switch..case的处理。

下面代码,就是针对上面的switch..case 进行使用策略模式。

首先不管三七二十一,你先定义一个接口,这个接口就是策略类接口。找出共同的方法,这里定义了一个策略类接口,用来处理具体类的业务功能。

package com.device.state;

/**
 * 创建策略类接口
 * 
 * @author Kevin Luo
 *
 */
public interface DeviceStatusStrategy {
    /**
     * 处理状态接口
     * 
     * @param message
     * @param deviceInfo
     * @param data
     * @return
     */
    public boolean processingStatus(String message, String deviceInfo, byte[] data);
}

下面定义具体的实现类,用于处理业务,封装了具体的算法或行我。同时,实现策略类接口。

package com.device.resule;

import com.device.state.DeviceStatusStrategy;

/**
 * 具体类,实现测试接口
 * 
 * @author Kevin Luo
 *
 */
public class resultDID1500 implements DeviceStatusStrategy {
    /**
     * 实现业务接口
     */
    @Override
    public boolean processingStatus(String message, String deviceInfo, byte[] data) {
        // TODO Auto-generated method stub
        System.out.println(message + "1500业务处理......" + deviceInfo);
        return true;
    }

}

另外一个具体实现类也是一样的事情,定一个具体实现类,用于处理业务。同时,实现策略类接口。其他的也都是一样的,只是类名不同而已,其他就不一一列举了。

package com.device.resule;

import com.device.state.DeviceStatusStrategy;

/**
 * 具体类,实现测试接口
 * 
 * @author Kevin Luo
 *
 */
public class saveDeviceState2100 implements DeviceStatusStrategy {

    /**
     * 实现业务接口
     */
    @Override
	public boolean processingStatus(String message, String deviceInfo, byte[] data) {
		// TODO Auto-generated method stub
		System.out.println("2100业务处理......");
		return true;
	}

}

我们来在创建一个Context上下文类,维护一个对Strategy对象的引用。

package com.device.state;

/**
 * Context上下文类,维护一个对Strategy对象的引用。
 * 
 * @author Kevin Luo
 *
 */
public class DeviceStatusContext {
    /**
     * 声明一个策略类接口,用于调用具体的实现类
     */
    private DeviceStatusStrategy deviceStatusStrategy;

    public DeviceStatusContext(DeviceStatusStrategy deviceStatusStrategy) {
        this.deviceStatusStrategy = deviceStatusStrategy;
    }

    /**
     * 执行策略类接口,会调用具体的实现类中的方法
     * 
     * @param message
     * @param deviceInfo
     * @param data
     * @return
     */
    public boolean executeStrategy(String message, String deviceInfo, byte[] data) {
        return deviceStatusStrategy.processingStatus(message, deviceInfo, data);
    }

}

最后,做了一个用于初始化上下文的一个类,用于外部调用。

这里面包含了两种实现方式

        第一种方式:获取对应的状态码,进行map查询,查询出对应的具体类对象

        第二种方式:通过配置文件的形式,获取对应的具体实现类,通过反射获取上下文对象,在进行调用
            这种方式,更加的灵活,当需要添加状态的时候,只需要添加对应的状态类,然后在配置文件中添加状态类地址就可以实现增加,非常的灵活,不需要修改内部代码,符合开闭原则。

package com.device.state;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import com.device.resule.resultDID1500;
import com.device.resule.saveDevcieStateInfo1888;
import com.device.resule.saveDeviceState2100;
import com.device.resule.saveWifiInfo5100;
import com.device.resule.saveWifiState2200;
import com.device.resule.seeWifiStateResult2280;
import com.device.utils.PropertyUtils;

/**
 * 具体的调用类
 * 
 * @author Kevin Luo
 *
 */
public class ResultHandle {
    //创建一个关系型map,用来存储对象,value值为策略类
    private static Map mapStrategy = new HashMap();;
    //初始化map对象,存储各个需要使用的具体类
    static {
        mapStrategy.put("1500", new resultDID1500());
        mapStrategy.put("2100", new saveDeviceState2100());
        mapStrategy.put("5100", new saveWifiInfo5100());
        mapStrategy.put("2200", new saveWifiState2200());
        mapStrategy.put("2280", new seeWifiStateResult2280());
        mapStrategy.put("1888", new saveDevcieStateInfo1888());
    }
    private DeviceStatusContext deviceStatusContext;

    /**
     * 第一种方式:获取对应的状态码,进行map查询,查询出对应的具体类对象
     * 
     * @param message
     * @param type
     * @param data
     * @return
     */
    public boolean handleDeviceStatusStrategy(String message, String type, byte[] data) {
        deviceStatusContext = new DeviceStatusContext(mapStrategy.get(type));
        return deviceStatusContext.executeStrategy(message, type, data);
    }

    /**
     * 第二种方式:通过配置文件形式,获取对应的具体实现类,通过反射获取上下文对象,在进行调用
     * 这种方式,更加的灵活,当需要添加状态的时候,只需要添加类型,然后在配置文件中添加类地址就可以实现增加
     * 
     * @param message
     * @param type
     * @param data
     * @return
     */
    public boolean handleStrategy(String message, String type, byte[] data) {
        String value = PropertyUtils.getValue("device" + type);
        this.CreateDeviceStateStrategy(value);
        return deviceStatusContext.executeStrategy(message, "123123123", data);
    }

    /**
     * 将具体类的对象地址通过反射生成上下文对象
     * 
     * @param type
     */
    public void CreateDeviceStateStrategy(String type) {
        Class clz;
        try {
            clz = Class.forName(type);
            Constructor constructor = clz.getConstructor();
            DeviceStatusStrategy deviceStatusStrategy = (DeviceStatusStrategy) constructor.newInstance(null);
            deviceStatusContext = new DeviceStatusContext(deviceStatusStrategy);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

这个是配置类,在deviceState.properties文件中配置对应的具体类地址。用于通过反射时获取上下文的对象。

device1500 = com.device.resule.resultDID1500
device2100 = com.device.resule.saveDeviceState2100
device5100 = com.device.resule.saveWifiInfo5100
device2200 = com.device.resule.saveWifiState2200
device2280 = com.device.resule.seeWifiStateResult2280
device1888 = com.device.resule.saveDevcieStateInfo1888

下来开始测试类,第一种方式以及第二种方式也都能正常的运行成功。

package com.device.test;

import com.device.state.ResultHandle;

public class DeviceStateTest {
    public static void main(String[] args) {

        ResultHandle rh = new ResultHandle();
        //第一种方式,运行成功
        rh.handleDeviceStatusStrategy("1111111", "1500", new byte[0]);
        //第二种方式,也运行成功
        rh.handleStrategy("1111111", "2100", new byte[0]);
    }
}

源码地址:

https://download.csdn.net/download/qq_19348391/10804100

小伙伴们有什么好的建议,欢迎在底下留言。

你可能感兴趣的:(设计模式)