策略模式原理及Java代码实例
一、策略模式的定义
—— 定义了一组算法,将每个算法包装起来,并且使它们之间可以互换
—— 策略模式使这些算法在客户端调用它们的时候能够相互不影响的变化,改变不同算法的实现方式不影响客户端的使用,即策略模式让算法独立于使用它的客户端而独立变化。
策略模式在Java中处处可以体现,TreeSet和TreeMap中均存在这样的构造方法:TreeSet(Comparator<? super E> comparator)
和TreeMap(Comparator<? superK> comparator)
,对它的描述为:构造一个空的TreeSet,它根据指定比较器进行排序。这里的指定比较器就是我们根据需要自己写的“算法”,这就是策略模式最基本的使用方式。
策略模式体现了两个非常基本的面向对象设计的原则:
1. 封装变化的概念。
2. 编程中使用接口,而不是对接口的实现
二、策略模式的角色组成
抽象策略角色:策略类,通常由一个接口或者抽象类实现
具体策略角色:包装了相关的算法和行为
环境角色:持有一个策略类的引用,最终给客户端调用的
四、编写策略模式的一般步骤:
1. 对策略对象定义一个公共接口
2. 编写具体策略类,该类实现了上面的接口
3. 在使用策略对象的类(即:环境角色)中保存一个对策略对象的引用
4. 在使用策略对象的类中,实现对策略对象的set和get方法(注入)或者使用构造方法完成赋值
5. 客户端进行调用
五、Java实现代码
要求:有这样一个类Class Person,包含id、name、age属性,有若干了Person对象存储在List中,要求对他们进行排序,分别按照名字、年龄、id进行排序(要有正序与倒序两种方式)。如果年龄或者姓名重复,则按照id的正序进行排列。要求使用策略模式进行。
思路分析:可以将若干Person类存放在ArrayList中,然后利用Collections中的 sort(List<T> list,Comparator<? super T> c)方法根据指定比较器产生的顺序对指定列表进行排序,我们要实现具体的比较规则,由于Comparator是一个接口,正好可以作为步骤一中的抽象策略角色。
1. 对策略对象定义一个公共接口
省了一步,直接用接口Comparator即可
2. 编写具体策略类,该类实现了上面的接口
按name进行排序的具体策略类SortByName,其它SortById和SortByAge与之类似:
package com.StrategyJob; import java.util.Comparator; public class SortByName implements Comparator { private int sortType = 0 ; // 定义标记位,默认是采用升序排列 @Override public int compare(Object arg0, Object arg1) { Person p0 = (Person)arg0 ; Person p1 = (Person)arg1 ; String name0 = p0.name ; String name1 = p1.name ; int id0 = p0.id ; int id1 = p1.id ; if(name0.endsWith(name1)){ return id0 - id1 ; } if(this.sortType != 0 ){ return name1.compareTo(name0); }else{ return name0.compareTo(name1); } } // 设置排序类型 public void setSortType(int sign) { this.sortType = sign ; } }
3. 在使用策略对象的类(即:环境角色)中保存一个对策略对象的引用
; 在使用策略对象的类中,实现对策略对象的set和get方法(注入)或者使用构造方法完成赋值
这里3和4的步骤是在一起的
package com.StrategyJob; import java.util.Comparator; public class Environment { private Comparator comparator ; // 私有的抽象策略角色的引用 public Environment(Comparator comp) { this.comparator = comp ; } public void setComparator(Comparator comp){ this.comparator = comp ; } public Comparator getComparator(){ return this.comparator; } }
5. 客户端进行调用
package com.StrategyJob; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; public class Client { public static void main(String[] args){ // 按姓名name进行排序 SortByName sortbyname = new SortByName() ; Environment environment = new Environment(sortbyname); Person p1 = new Person(); Person p2 = new Person(); Person p3 = new Person(); Person p4 = new Person(); ArrayList list = new ArrayList(); p1.setName("zhangsan"); p1.setId(1); p1.setAge(20); p2.setName("lisi"); p2.setId(5); p2.setAge(25); p3.setName("wangwu"); p3.setId(16); p3.setAge(5); p4.setName("zhangsan"); p4.setId(6); p4.setAge(5); list.add(p1); list.add(p2); list.add(p3); list.add(p4); System.out.println("--------------------- 按照name升序排列 -----------------------"); // 按照name进行排序 Collections.sort(list, environment.getComparator()); for(Iterator iter = list.iterator() ; iter.hasNext() ; ){ Person p = (Person)iter.next(); String name = p.name ; int id = p.id ; System.out.println(name + " "+ id); } sortbyname.setSortType(1); System.out.println("--------------------- 按照name降序排列start -----------------------"); // 按照name进行排序 Collections.sort(list, environment.getComparator()); for(Iterator iter = list.iterator() ; iter.hasNext() ; ){ Person p = (Person)iter.next(); String name = p.name ; int id = p.id ; System.out.println(name + " "+ id); } System.out.println("---------------------- 按照id升序排列 ----------------------"); SortById sortbyid = new SortById(); environment.setComparator(sortbyid); Collections.sort(list, environment.getComparator()); for(Iterator iter = list.iterator() ; iter.hasNext() ; ){ Person p = (Person)iter.next(); int id = p.id ; System.out.println(id + ""); } System.out.println("---------------------- 按照id降序排列 ----------------------"); sortbyid.setSortType(1); Collections.sort(list, environment.getComparator()); for(Iterator iter = list.iterator() ; iter.hasNext() ; ){ Person p = (Person)iter.next(); int id = p.id ; System.out.println(id + ""); } System.out.println("---------------------- 按照age升序排列 ----------------------"); SortByAge sortbyage = new SortByAge(); environment.setComparator(sortbyage); Collections.sort(list, environment.getComparator()); for(Iterator iter = list.iterator() ; iter.hasNext() ; ){ Person p = (Person)iter.next(); int age = p.age ; System.out.println(age + " " + p.id); } System.out.println("---------------------- 按照age降序排列 ----------------------"); sortbyage.setSortType(1); Collections.sort(list, environment.getComparator()); for(Iterator iter = list.iterator() ; iter.hasNext() ; ){ Person p = (Person)iter.next(); int age = p.age ; System.out.println(age + " " + p.id); } } }
6. 运行结果
注:一般一个类中的private成员变量都会跟着setXXX和getXXX方法进行赋值和改变值的,只在类的内部使用该成员变量。
坚持每天的学习,加油!!!