0
点赞
收藏
分享

微信扫一扫

设计模式(行为型设计模式——策略模式)

老罗话编程 03-23 07:30 阅读 3

策略模式是一种常用的模式,在日常使用中非常频繁

而且策略模式的实现方式也有很多种

这里我只讲一下两种简单实用的方式

首先是基本策略模式(包括一个策略接口、多个具体策略类和一个上下文类。在上下文类中持有一个策略对象,并将调用委托给策略对象)
比如我们常用的Comparator接口,我们定义了一个比较方法(策略接口)

public interface Comparator<T> {

    int compare(T o1, T o2);
}

然后还需要一个具体的策略类(比如我要比较狗的食量大小)

public class DogComparator implements Comparator<Dog> {
    @Override
    public int compare(Dog o1, Dog o2) {
        if (o1.food < o2.food)
            return -1;
        else if (o1.food > o2.food)
            return 1;
        else
            return 0;
    }
}

这里还需要一个狗对象

public class Dog {

    int food;

    public Dog(int food) {
        this.food = food;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "food=" + food +
                '}';
    }
}

最后还需要一个上下文类

public class Sorter<T> {

    // 从小到大
    public void sort(T[] arr, Comparator<T> comparator) {
        for (int i = 0; i < arr.length; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                if (comparator.compare(arr[i], arr[j]) > 0) {
                    T temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }

    // 从大到小
    public void sort1(T[] arr, Comparator<T> comparator) {
        for (int i = 0; i < arr.length; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                if (comparator.compare(arr[i], arr[j]) < 0) {
                    T temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }

}

然后写个demo测试一下

public class Test {

    public static void main(String[] args) {
        Dog[] dogs = new Dog[]{new Dog(3), new Dog(1), new Dog(2)};
        Sorter<Dog> sorter = new Sorter<>();
        sorter.sort(dogs, new DogComparator());
        System.out.println(Arrays.toString(dogs));
    }
}

运行结果

在这里插入图片描述

看到这里很多人肯定是有疑问的,我就比较一个狗的食量大小怎么这么复杂?先不要急,模式之所以称之为模式,那么说明它不是用来处理单一的问题的,而是用来处理某一些相同类型的问题的。

比如接下来我们来了一只猫,它也要比较大小

public class Cat {
    int weight, height;

    public Cat(int weight, int height) {
        this.weight = weight;
        this.height = height;
    }

    @Override
    public String toString() {
        return "Cat{" +
                "weight=" + weight +
                ", height=" + height +
                '}';
    }
}

但是怎么比呢?比如我想根据体重比,这个时候策略模式的优点就能体现出来了
我们添加一个根据体重比较的策略类

public class CatWeightComparator implements Comparator<Cat> {
    @Override
    public int compare(Cat o1, Cat o2) {
        if (o1.weight < o2.weight)
            return -1;
        else if (o1.weight > o2.weight)
            return 1;
        else
            return 0;
    }
}

一样的我们执行一下

public class Test {

    public static void main(String[] args) {
//        Dog[] dogs = new Dog[]{new Dog(3), new Dog(1), new Dog(2)};
//        Sorter<Dog> sorter = new Sorter<>();
//        sorter.sort(dogs, new DogComparator());
//        System.out.println(Arrays.toString(dogs));

        Cat[] cats = new Cat[]{new Cat(3, 3), new Cat(1, 1), new Cat(2, 2)};
        Sorter<Cat> sorter = new Sorter<>();
        sorter.sort(cats, new CatWeightComparator());
        System.out.println(Arrays.toString(cats));
    }
}

结果是正常的

在这里插入图片描述
我还想根据身高比,那么加一个身高的策略类

public class CatHeightComparator implements Comparator<Cat> {
    @Override
    public int compare(Cat o1, Cat o2) {
        if (o1.height < o2.height)
            return -1;
        else if (o1.height > o2.height)
            return 1;
        else
            return 0;
    }
}

这里我们调用sort1方法,让它从大到小排序

public class Test {

    public static void main(String[] args) {
//        Dog[] dogs = new Dog[]{new Dog(3), new Dog(1), new Dog(2)};
//        Sorter<Dog> sorter = new Sorter<>();
//        sorter.sort(dogs, new DogComparator());
//        System.out.println(Arrays.toString(dogs));

//        Cat[] cats = new Cat[]{new Cat(3, 3), new Cat(1, 1), new Cat(2, 2)};
//        Sorter<Cat> sorter = new Sorter<>();
//        sorter.sort(cats, new CatWeightComparator());
//        System.out.println(Arrays.toString(cats));

        Cat[] cats = new Cat[]{new Cat(3, 3), new Cat(1, 1), new Cat(2, 2)};
        Sorter<Cat> sorter = new Sorter<>();
        sorter.sort1(cats, new CatHeightComparator());
        System.out.println(Arrays.toString(cats));
    }
}

看一下结果

在这里插入图片描述
可以发现当我们来了新的对象比如鸡鸭鱼肉的,我们想比较他们的任意属性只需要新写一个鸡鸭鱼肉的属性策略类就可以直接用了,想用其它算法也只需要在上下文类中添加就可以了,它们之间互相不关联不影响,这就是策略模式的作用!

好了下面我们再来看一下使用函数式接口来实现策略模式
这个是我比较喜欢用的一种方式,如果以前你只听说过策略模式可以替代if else但不知道怎么替代,那么下面这个就可以解释你的疑惑
这里我直接上我以前的代码,就不单独写示例了

import lombok.SneakyThrows;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * @author Sakura
 * @date 2023/12/19 11:16
 */
@Service
public class CallbackListenerStrategyContext {
    // 策略采用lambda的方法存储
    Map<String, Function<CallbackRoomInfoRequest, CallbackResponse>> strategyContextMap = new HashMap<>();

    @Resource
    CallbackListenerService callbackListenerService;

    @PostConstruct
    @SneakyThrows
    public void setStrategyMap() {
        // 配置回调方法
        strategyContextMap.put("createRoom",(callbackRoomInfoRequest)-> callbackListenerService.createRoom(callbackRoomInfoRequest));
        strategyContextMap.put("destroyRoom",(callbackRoomInfoRequest)-> callbackListenerService.destroyRoom(callbackRoomInfoRequest));
        strategyContextMap.put("updateRoomInfo",(callbackRoomInfoRequest)-> callbackListenerService.updateRoomInfo(callbackRoomInfoRequest));
        strategyContextMap.put("enterRoom",(callbackRoomInfoRequest)-> callbackListenerService.enterRoom(callbackRoomInfoRequest));
        strategyContextMap.put("exitRoom",(callbackRoomInfoRequest)-> callbackListenerService.exitRoom(callbackRoomInfoRequest));
        strategyContextMap.put("takeSeat",(callbackRoomInfoRequest)-> callbackListenerService.takeSeat(callbackRoomInfoRequest));
        strategyContextMap.put("leaveSeat",(callbackRoomInfoRequest)-> callbackListenerService.leaveSeat(callbackRoomInfoRequest));

    }

    public CallbackResponse callbackListener(String command, CallbackRoomInfoRequest callbackRoomInfoRequest){
        // 根据command获取对应的方法返回策略
        Function<CallbackRoomInfoRequest, CallbackResponse> callbackListenerFunc = strategyContextMap.get(command);
        return callbackListenerFunc.apply(callbackRoomInfoRequest);
    }
}

下面是具体的方法实现

import lombok.extern.java.Log;
import org.springframework.stereotype.Service;

/**
 * @author Sakura
 * @date 2023/12/19 11:42
 */
@Service
@Log
public class CallbackListenerService {

    // 此处用来统一处理多人视频房间回调++++++++++++++++++++++++++++++++++++++++++++

    // 创建房间回调
    public CallbackResponse createRoom(CallbackRoomInfoRequest callbackRoomInfoRequest){
        log.info("创建房间回调" + callbackRoomInfoRequest.toString());
        return CallbackResponse.success();
    }

    // 销毁房间回调
    public CallbackResponse destroyRoom(CallbackRoomInfoRequest callbackRoomInfoRequest){
        log.info("销毁房间回调" + callbackRoomInfoRequest.toString());
        return CallbackResponse.success();
    }

    // 更新房间回调
    public CallbackResponse updateRoomInfo(CallbackRoomInfoRequest callbackRoomInfoRequest){
        log.info("更新房间回调" + callbackRoomInfoRequest.toString());
        return CallbackResponse.success();
    }

    // 用户进房回调
    public CallbackResponse enterRoom(CallbackRoomInfoRequest callbackRoomInfoRequest){
        log.info("用户进房回调" + callbackRoomInfoRequest.toString());
        return CallbackResponse.success();
    }

    // 用户退房回调
    public CallbackResponse exitRoom(CallbackRoomInfoRequest callbackRoomInfoRequest){
        log.info("用户退房回调" + callbackRoomInfoRequest.toString());
        return CallbackResponse.success();
    }

    // 用户上麦回调
    public CallbackResponse takeSeat(CallbackRoomInfoRequest callbackRoomInfoRequest){
        log.info("用户上麦回调" + callbackRoomInfoRequest.toString());
        return CallbackResponse.success();
    }

    // 用户下麦回调
    public CallbackResponse leaveSeat(CallbackRoomInfoRequest callbackRoomInfoRequest){
        log.info("用户下麦回调" + callbackRoomInfoRequest.toString());
        return CallbackResponse.success();
    }
}

这个用起来也很简单

import com.jonsime.jonsimeShop.callback.CallbackListenerStrategyContext;
import com.jonsime.jonsimeShop.callback.CallbackResponse;
import com.jonsime.jonsimeShop.callback.CallbackRoomInfoRequest;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@Log
@RestController
@RequestMapping("/tx/callback")
public class TxController {

    @Autowired
    CallbackListenerStrategyContext callbackListenerStrategyContext;

    @PostMapping("/listener")
    public CallbackResponse callbackListener(@RequestParam Long sdkappid, @RequestParam String command,
                                   @RequestParam String contenttype, @RequestParam String clientip,
                                   @RequestParam String optplatform,
                                   @RequestBody CallbackRoomInfoRequest callbackRoomInfoRequest) {
        log.info("回调监听:" + "sdkappid:" + sdkappid + "  command:" + command + "  " + callbackRoomInfoRequest.toString());

        return callbackListenerStrategyContext.callbackListener(command, callbackRoomInfoRequest);
    }
}

上面这个如果用 if 大概是下面这样的

        if ("createRoom".equals(command)) {
            return callbackListenerService.createRoom(callbackRoomInfoRequest);
        } else if ("destroyRoom".equals(command)) {
            return callbackListenerService.destroyRoom(callbackRoomInfoRequest);
        } else if () {
            
        }

这样一对比…好像差不太多!if else似乎看起来更加简单明了!不过这的确就是函数式接口策略模式,大家习惯一下就好
其它实现方式就不讲了,大家自己了解一下知道有哪些就行

举报

相关推荐

0 条评论