策略模式--strategy

策略模式

含义:

策略模式(Strategy)属于对象行为型设计模式,
1.主要是定义一系列的算法
2.把这些算法一个个封装成拥有共同接口的单独的类,并且使它们之间可以互换。
  • 策略模式使这些算法在客户端调用它们的时候能够互不影响地变化。这里的算法不要狭义的理解为数据结构中算法,可以理解为不同的业务处理方法

策略模式由三个角色组成:

在这里插入图片描述

策略模式使用场景:

同一个系统中存在不同的逻辑算法,而彼此之间在不同场景中需要实现动态替换,

  • 支付方式
    可以选择:支付宝,微信,银联等,彼此之间就可以相互替换,
  • 打折促销活动
    有双11活动,双12活动,会员活动,彼此之间可以相互替换

案例 :排序问题

1. int[ ]数组

Sorter1

public class Sorter1 {

    public void sort(int[] arr) {
        for(int i=0; i<arr.length - 1; i++) {
            int minPos = i;

            for(int j=i+1; j<arr.length; j++) {
                minPos = arr[minPos]> arr[j] ? j  : minPos;
            }
            swap(arr, i, minPos);
        }
    }

    //sort(int)
    void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

}

测试:

    @Test
    public void test01() {
        int[] a = {9, 2, 3, 5, 7, 1, 4};
        Sorter1 sorter = new Sorter1();
        sorter.sort(a);
        System.out.println(Arrays.toString(a));
    }

在这里插入图片描述

2. Cat[ ]数组

Comparable接口https://blog.csdn.net/weixin_48052161/article/details/115414069

在这里插入图片描述

Cat

public class Cat implements Comparable<Cat> {

    Integer weight, height;

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

    @Override
    public int compareTo(Cat c) {
        if(this.weight < c.weight) return -1;
        else if(this.weight > c.weight) return 1;
        else return 0;
    }

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

Sorter2

public class Sorter2 {

    public void sort(Cat[] arr) {

        for (int i = 0; i < arr.length - 1; i++) {
            int minPos = i;
            for (int j = i + 1; j < arr.length; j++) {
                minPos = arr[minPos].compareTo(arr[j]) == 1 ? j : minPos;
            }
            swap(arr, i, minPos);
        }
    }


    void swap(Cat[] arr, int i, int j) {
        Cat temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

}

测试:

@Test
    public void test02() {
       Cat[] a= new Cat[]{new Cat(3,3),new Cat(5,5),new Cat(1,1)};

        Sorter2 sorter = new Sorter2();
        sorter.sort(a);
        System.out.println(Arrays.toString(a));
    }

在这里插入图片描述

3. 策略模式 定制规则

comparator 定制排序

在这里插入图片描述

Sorter3

public class Sorter3<T> {

    public void sort(T[] arr, Comparator<T> comparator) {

        for (int i = 0; i < arr.length - 1; i++) {
            int minPos = i;
            for (int j = i + 1; j < arr.length; j++) {
                minPos = comparator.compare(arr[minPos],arr[j])==1 ? j : minPos;
            }
            swap(arr, i, minPos);
        }
    }


    void swap(T[] arr, int i, int j) {
        T temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

}

测试 ; cat比较 按体重降升序,如果体重相同身高降序排列

  //按体重降升序,如果体重相同身高降序
    @Test
    public void test03() {
        Cat[] a= new Cat[]{new Cat(1,3),new Cat(3,3),new Cat(1,1),new Cat(1,2)};

        Sorter3<Cat> sorter = new Sorter3();
        sorter.sort(a,(o1,o2)->{
            if(o1.weight<o2.weight){
                return -1;
            }else if(o1.weight>o2.weight){
                return 1;
            }else{
                //Integer默认重写的compareTo方法,模式是从小到大排序
                return -o1.height.compareTo(o2.height);
            }
        });
        System.out.println(Arrays.toString(a));
    }

在这里插入图片描述

Integer 实现了Comparable接口 ,且重写了compareTo方法,模式是从小到大排序

在这里插入图片描述
在这里插入图片描述

4.JDK源码中策略模式排序

Arrays.sort()在这里插入图片描述
  • 在JDK中,我们调用数组工具类Arrays的一个排序方法sort时,可以使用默认的排序规则(升序),也可以自定义指定排序的规则,也就是可以自定义实现升序排序还是降序排序,方法的源码如下:
 @Test
    public void test04() {
        Cat[] a= new Cat[]{new Cat(1,3),new Cat(3,3),new Cat(1,1),new Cat(1,2)};

       Arrays.sort(a,(o1,o2)->{
           if(o1.weight<o2.weight){
               return -1;
           }else if(o1.weight>o2.weight){
               return 1;
           }else{
               //Integer默认重写的compareTo方法,模式是从小到大排序
               return -o1.height.compareTo(o2.height);
           }
       });

        System.out.println(Arrays.toString(a));
    }

案例:支付问题

1、创建一个策略接口

PayStrategry

public interface PayStrategry {

    boolean pay(int money);//支付

    BigDecimal queryBalance(String accountNo);//查询余额
}

2、接下来定义2个实现类示例

AliPayStrategy


public class AliPayStrategy implements PayStrategry{
    @Override
    public boolean pay(int money) {
        System.out.println("支付宝支付成功");
        return true;
    }

    @Override
    public BigDecimal queryBalance(String accountNo) {
        System.out.println("支付宝余额10元");
        return new BigDecimal(10);
    }

}

WechatPayStrategy


public class WechatPayStrategy implements PayStrategry{
    @Override
    public boolean pay(int money) {
        System.out.println("微信支付成功");
        return true;
    }
    @Override
    public BigDecimal queryBalance(String accountNo) {
        System.out.println("微信余额10元");
        return new BigDecimal(10);
    }

}

3.一般方法测试

public class TestPayStrategy {
    public static void main(String[] args) {
        String pay = "aliPay";
        PayStrategy payStrategy = null;
        if(pay.equals("aliPay")){
            payStrategy = new AliPayStrategy();
        }else if(pay.equals("wechatPay")){
            payStrategy = new WechatPayStrategy();
        }
        payStrategy.pay(10);
        payStrategy.queryBalance("XXX");
    }
}

通过枚举类的实现方式来改造一下测试方法:

PayEnum

public enum PayEnum {

    AliPay("aliPay",new AliPayStrategy()),
    WechatPay("wechatPay",new WechatPayStrategy());

    private String key;
    private PayStrategry value;

    PayEnum(String key, PayStrategry value) {
        this.key = key;
        this.value = value;
    }
    public static PayStrategry getValue(String key){
        for (PayEnum payEnum : PayEnum.values()){
            if (payEnum.key.equals(key)){
                return payEnum.value;
            }
        }

        return new AliPayStrategy();//没有合适key则默认阿里支付
    }

}

测试一下

public class TestPayStrategy {
    public static void main(String[] args) {
        String pay = "aliPay";
        PayStrategry payStrategy = PayEnum.getValue(pay);
        payStrategy.pay(10);
        payStrategy.queryBalance("XXX");
    }

在这里插入图片描述

现在增加一种支付方式,icbc支付

  • 只需要对枚举类代码进行修改

PayEnum

public enum PayEnum {

    AliPay("aliPay",new AliPayStrategy()),
    WechatPay("wechatPay",new WechatPayStrategy()),

    ICBCPay("icbc", new PayStrategry() {
        @Override
        public boolean pay(int money) {
            System.out.println("icbc支付成功");
            return true;
        }

        @Override
        public BigDecimal queryBalance(String accountNo) {
            System.out.println("icbc余额10元");
            return new BigDecimal(10);
        }
    });

    private String key;
    private PayStrategry value;

    PayEnum(String key, PayStrategry value) {
        this.key = key;
        this.value = value;
    }
    public static PayStrategry getValue(String key){
        for (PayEnum payEnum : PayEnum.values()){
            if (payEnum.key.equals(key)){
                return payEnum.value;
            }
        }


        return new AliPayStrategy();//没有合适key则默认阿里支付
    }

}

测试一下

public class TestPayStrategy {
    public static void main(String[] args) {
        String pay = "aliPay";
        PayStrategry payStrategy = PayEnum.getValue(pay);
        payStrategy.pay(10);
        payStrategy.queryBalance("XXX");
        
        System.out.println("----------------------------");
        
        PayStrategry payStrategy1 = PayEnum.getValue("icbc");
        payStrategy1.pay(10);
        payStrategy1.queryBalance("XXX");

    }

}

在这里插入图片描述

这么改写之后,如果以后新增了其他支付方式只需要再枚举类中新怎过一种枚举类型并且实现自定义支付逻辑之后,其他代码就无需变更

在这里插入图片描述

策略模式总结

优点

  • 结构清晰明了、使用简单直观;
  • 耦合度相对而言较低,扩展方便;
  • 操作封装也更为彻底,数据更为安全;

缺点

  • 策略类数量会增多,每个策略都是一个类,复用的可能性很小,增加维护难度
  • 所有的策略类都需要对外暴露

应用场景

  1. 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。多个类只有算法或行为上稍有不同的场景
  2. 一个系统需要动态地在几种算法中选择一种。算法需要自由切换的场景
  3. 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
  4. 需要屏蔽算法规则的场景

注意事项

  • 如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值