zoukankan      html  css  js  c++  java
  • Strategy策略模式

    策略模式(Strategy):

    它定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法的变化不会影响到使用算法的客户。(原文:The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.)

    动机:

    在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。

    如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题?

    策略模式就能使算法与对象本身解耦,能够在需要时透明的更改对象的算法。

    通俗点讲,策略模式就是将对象本身的算法进行抽象,从而从对象本身中剥离出来。
    比如对某一类对象obj进行比较,我们可能会采取多种比较策略,如果每一种比较策略都在对象obj中写一个实现方法,这个类将会膨胀。
    在我们看来,所有的比较归根结底就是比较出两个对象的大小,所以我们可以对这一部分进行抽象,抽成一个comparator比较器,由外部调用处对这个比较器进行注入。这样我们就能灵活的控制到底使用哪一种比较规则了。

    举例:

    比较学生,1:按年龄比较   2:按身高比较

    public interface Comparator<T> {
        public int compare(T obj1, T obj2);
    }
    public class Student {
        private String name;
        private int age;
        private double height;
        private Comparator<Student> comparator;
        
    
        public Comparator<Student> getComparator() {
            return comparator;
        }
    
        public void setComparator(Comparator<Student> comparator) {
            this.comparator = comparator;
        }
    
        public double getHeight() {
            return height;
        }
    
        public void setHeight(double height) {
            this.height = height;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public int compare(Student s) {
            return this.comparator.compare(this, s);
        }
    }
    public class StuAgeComparator implements Comparator<Student> {
    
        @Override
        public int compare(Student s1, Student s2) {
            if(s1.getAge() > s2.getAge()){
                return 1;
            } else if (s1.getAge() == s2.getAge()){
                return 0;
            } else {
                return -1;
            }
        }
        
    
    }
    public class StuHeightComparator implements Comparator<Student> {
    
        @Override
        public int compare(Student s1, Student s2) {
            if(s1.getHeight() > s2.getHeight()){
                return 1;
            } else if (s1.getHeight() == s2.getHeight()){
                return 0;
            } else {
                return -1;
            }
        }
        
    
    }

    客户端调用:

    public class Client {
        public static void main(String[] args) {
            Student s1 = new Student();
            s1.setName("张三");
            s1.setAge(18);
            s1.setHeight(1.7);
            Student s2 = new Student();
            s2.setName("李四");
            s2.setAge(15);
            s2.setHeight(1.80);
            
            s1.setComparator(new StuAgeComparator());
            System.out.println(s1.compare(s2));
            s1.setComparator(new StuHeightComparator());
            System.out.println(s1.compare(s2));
        }
    }

    其实我上面讲的就是JDK中的Comparator这个接口,但是好像还少了点什么,少的就是Comparable这个接口。

    这个接口是为通用的排序做准备的。

    我们知道Conllections.sort(List<T> args)这个方法是对List中的对象进行排序,不管它里面装的是什么对象。那么我们想对任意的对象进行排序的话,就不能用具体的排序的实现方法,也就是要对排序进行抽象,而排序中重要的一环就是比较两个对象的大小,所以归根结底就是对比较大小进行抽象,使用子类的实现。

    所以我们就考虑让所有类型的对象都实现统一的接口,对象比较时都使用这个接口的比较方法,故最终比较时就会使用子类的比较方法的实现来进行大小比较。

    例:

    public interface Comparable<T> {
        public int compareTo(T obj);
    }
    public class Student implements Comparable<Student>{
        private String name;
        private int age;
        private double height;
        private Comparator<Student> comparator = new StuAgeComparator();
        
          // getter/setter方法  
    
        public int compareTo(Student s) {
            return this.comparator.compare(this, s);
        }
    }    

    客户端调用代码:

    public class ClientSort {
        public static void main(String[] args) {
            Student s1 = new Student();
            s1.setName("张三");
            s1.setAge(18);
            s1.setHeight(1.7);
            Student s2 = new Student();
            s2.setName("李四");
            s2.setAge(15);
            s2.setHeight(1.80);
            Student s3 = new Student();
            s3.setName("王五");
            s3.setAge(21);
            s3.setHeight(1.65);
            Comparable<Student>[] stus = new Student[3];
            stus[0] = s1;
            stus[1] = s2;
            stus[2] = s3;
            stus = DataSorter.sort(stus);
            for(Comparable<Student> s : stus){
                System.out.println(((Student)s).getName() + ":" + ((Student)s).getAge());
            }
        }
    }

    输出:

    李四:15
    张三:18
    王五:21

    所以,Comparable这个接口与Strategy策略模式是不相关的,它主要的作用是统一比较接口。

    Comparator的实现才是具体的比较策略。

  • 相关阅读:
    Solr服务在Linux上的搭建详细教程
    Linux服务器上安装JDK小白教程
    request和response中文乱码问题后台处理办法
    Redis的五种数据类型及方法
    Java类装载器ClassLoader
    Git快速入门和常用命令
    redis在Linux上的部署和jedis简单使用
    Linux常用基础命令
    JDK1.7中HashMap底层实现原理
    微信电脑版无法显示图片无法下载文件
  • 原文地址:https://www.cnblogs.com/kevin-yuan/p/4185303.html
Copyright © 2011-2022 走看看