设计模式系列之策略模式

概述:

策略模式定义了一系列的算法,并将这些算法一个个封装起来, 并且使它们可相互替换

emmm,这是什么意思呢?单看定义确实有那么一点点晦涩难懂,不如先看下策略模式有哪些角色。
策略模式的三个角色:
1、策略角色:策略是一个接口,接口中定义了要实现的算法。
2、具体策略角色:具体策略是实现策略接口的类,并将接口中的方法实现。
3、策略上下文角色:策略上下文依赖于策略接口的类,也就是说上下文包含有策略声明的变量。

其实就是策略模式需要一个接口(这个接口就是策略角色),接口中有方法。既然我们创建了接口,那肯定是要用他的,所以需要一个类(具体策略角色)来实现这个接口。至于策略上下文角色,他就是一个依赖于策略接口的类,类中的方法通过调用策略接口来完成对应的功能。

下面通过一个例子来了解下策略模式和上面的定义。

我们假设写个接口,来实现狗的体重的大小比较。

定义接口:(策略角色)

package com.dong.patten.strategy;

/**
 * @author 雪浪风尘
 * @Remember Keep thinking
 */
public interface Comparator<T> {
    int compare(T o1,T o2);
}

一个实现接口的类(这个类就是具体策略角色)

package com.dong.patten.strategy;

/**
 * @author 雪浪风尘
 * @Remember Keep thinking
 */
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;
    }
}

因为是比较狗的食量,所以需要创建狗的对象。当然了这个是这个例子需要创建对象,具体的情况还要具体对待。
dog对象:

package com.dong.patten.strategy;

/**
 * @author 雪浪风尘
 * @Remember Keep thinking
 */
public class Dog  {
    int food;

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

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

策略上下文角色:

package com.dong.patten.strategy;

/**
 * @author 雪浪风尘
 * @Remember Keep thinking
 */
public class Sorter<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[j],arr[minPos])==-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;
    }
}

这里只是一个简单的排序,将传入的数组中的对象进行简单的排序。
至此,策略模式主要的部分已经完成,我们写个例子测试一下;

package com.dong.patten.strategy;

import java.util.Arrays;

/**
 * @author 雪浪风尘
 * @Remember Keep thinking
 * 策略模式封装的是做一件事情的不同的执行方式
 */
public class Main {
    public static void main(String[] args) {
        Dog[] a={new Dog(3),new Dog(5),new Dog(1)};
        Sorter<Dog> sorter=new Sorter();
        sorter.sort(a,new DogComparator());
        System.out.println(Arrays.toString(a));
    }
}

来看下结果:

[Dog{food=1}, Dog{food=3}, Dog{food=5}]

看到这里,你是否会想:写这么多不是挺麻烦的,直接定义对象,然后比较不就可以了。

对于单个对象来说,确实是可以的,但是如果后期要维护、修改,或者新增对象呢?比如新增猫对象的比较,我们可能还需要在原有基础上,需要原来方法中的代码,这样一来,就违反了“开-闭原则”。
使用策略模式,当我们新增时,只需要添加新的具体策略角色即可,不需要对方法进行修改,既满足了“开-闭原则”,又不会因为修改代码,而造成未知的bug。

比如,这波我们新增一个猫对象的比较:
原有的策略角色、策略上下文角色都不需要修改,只需要新增一个具体策略角色即可。

package com.dong.patten.strategy;

/**
 * @author 雪浪风尘
 * @Remember Keep thinking
 */
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;

    }
}

因为参数类型是猫这个对象,所以需要创建猫的对象:

package com.dong.patten.strategy;

/**
 * @author 雪浪风尘
 * @Remember Keep thinking
 */
public class Cat{
    int height,weight;

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

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

OK,测试一下:

package com.dong.patten.strategy;

import java.util.Arrays;

/**
 * @author 雪浪风尘
 * @Remember Keep thinking
 * 策略模式封装的是做一件事情的不同的执行方式
 */
public class Main {
    public static void main(String[] args) {
        Cat[] a={new Cat(3,3),new Cat(5,5),new Cat(1,1)};
//        Dog[] a={new Dog(3),new Dog(5),new Dog(1)};
        Sorter<Cat> sorter=new Sorter();
        sorter.sort(a,new CatWeightComparator());
        System.out.println(Arrays.toString(a));
    }
}

运行结果:

[Cat{height=1, weight=1}, Cat{height=3, weight=3}, Cat{height=5, weight=5}]

可以看到,我们只需要新增具体策略角色即可,不需要修改什么接口啦,上下文对象啦,而且也比较省事。

代码已经提交到github上:
https://github.com/PonnyDong/pattern
后续的代码的更新也会在上面进行更新

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值