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的实现才是具体的比较策略。

  • 相关阅读:
    Django(app的概念、ORM介绍及编码错误问题)
    Django(完整的登录示例、render字符串替换和redirect跳转)
    Construct Binary Tree from Preorder and Inorder Traversal
    Single Number II
    Single Number
    Binary Tree Level Order Traversal II
    Binary Tree Level Order Traversal
    Binary Tree Zigzag Level Order Traversal
    Recover Binary Search Tree
    Add Binary
  • 原文地址:https://www.cnblogs.com/kevin-yuan/p/4185303.html
Copyright © 2011-2022 走看看