策略模式中体现了两个非常基本的面向对象设计的原则:
1.封装变化的概念。
2.编程中使用接口,而不是对接口的实现。
策略模式的定义:
定义一组算法,将每个算法都封装起来,并使它们之间可以互换。策略模式使这些算法在客户端调用它们的时候能够互不影响地变化。
策略模式的意义:
策略模式使开发人员能够开发出由许多可替换的部分组成的软件,并且各个部分之间是弱连接的关系。
弱连接的特性使软件具有更强的可扩展性,易于维护;更重要的是,它大大提高了软件的可重用性。
策略模式的组成
1.抽象策略角色:策略类,通常由一个接口或者抽象类实现。
2.具体策略角色:包装了相关的算法和行为。
3.环境角色:持有一个策略类的引用,最终给客户端调用的。
策略模式的实现
1.策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使它们可以相互替换。
2.策略模式使得算法可以在不影响到客户端的情况下发生变化。使用策略模式可以把行为和环境分割开来。
3.环境类负责维持和查询行为类,各种算法则在具体策略中提供。由于算法和环境独立开来,算法的修改都不会影响环境和客户端。
策略模式的编写步骤
1.对策略对象定义一个公共接口。
2.编写策略类,该类实现了上面的公共接口。
3.在使用策略对象的类中保存一个对策略对象的引用。
4.在使用策略对象的类中,实现对策略对象的set和get方法(注入)或者使用构造方法完成赋值。
策略模式的优点
1.策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。
2.使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。
策略模式的缺点
1.客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道算法或行为的情况。
2.由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。
下面举个例子来说明一下
有一个Person类,属性有id,name,age,分别按照id,name,age进行正序和倒序的排列。
package com.zhouyu.strategy; public class Person { private int id; private String name; private int age; public Person() { } public Person(int id,String name,int age) { this.id = id; this.name = name; this.age = age; } public int getId() { return id; } public String getName() { return name; } public int getAge() { return age; } public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } }
这个是抽象策略角色,一个名为Strategy的接口
package com.zhouyu.strategy; import java.util.List; public interface Strategy { public void sort(List<Person> list); }
还有几个具体策略角色,他们都继承了Strategy接口
package com.zhouyu.strategy; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; public class ForIdUp implements Strategy,Comparator<Person> { @Override public void sort(List<Person> list) { Collections.sort(list,this); } @Override public int compare(Person o1, Person o2) { return o1.getId()-o2.getId(); } }
package com.zhouyu.strategy; import java.util.Collections; import java.util.Comparator; import java.util.List; public class ForIdDown implements Strategy,Comparator<Person> { @Override public void sort(List<Person> list) { Collections.sort(list,this); } @Override public int compare(Person o1, Person o2) { return o2.getId() - o1.getId(); } }
这里只给出了按照Id的正序和倒序,其他的请下载代码吧,这里就不重复写出了。
这个是环境角色
package com.zhouyu.strategy; import java.util.List; public class Environment { private Strategy strategy; public void setStrategy(Strategy strategy) { this.strategy = strategy; } public void sort(List<Person> list) { this.strategy.sort(list); } }
最后是测试用的类
package com.zhouyu.strategy; import java.util.ArrayList; import java.util.List; public class Client { private Environment environment = new Environment(); public static void main(String[] args) { List<Person> list = new ArrayList<Person>(); list.add(new Person(1,"刘备",30)); list.add(new Person(2,"关羽",29)); list.add(new Person(3,"张飞",28)); list.add(new Person(4,"赵云",26)); Client client = new Client(); Environment environment = new Environment(); //按照Id正序排序 ForIdUp idUp = new ForIdUp(); client.print(idUp,list); //按照Id倒序排序 ForIdDown idDown = new ForIdDown(); client.print(idDown,list); //按照name正序排序 ForNameUp nameUp = new ForNameUp(); client.print(nameUp,list); //按照name倒序排序 ForNameDown nameDown = new ForNameDown(); client.print(nameDown,list); //按照age正序排序 ForAgeUp ageUp = new ForAgeUp(); client.print(ageUp,list); //按照age倒序排序 ForAgeDown ageDown = new ForAgeDown(); client.print(ageDown,list); } public void print(Strategy strategy,List<Person> list) { environment.setStrategy(strategy); environment.sort(list); for(int i=0;i<list.size();i++) { Person person = list.get(i); System.out.println("序号:"+ person.getId() + ",姓名:" + person.getName() + ",年龄:" +person.getAge()); } System.out.println("--------------------------------------------------------------"); } }
写的不好,请大家多多指出错误。
不知道代码传到哪里,只好传到CSDN上了,有需要的自行下载
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:设计模式原来如此-策略模式(Strategy Pattern) - Python技术站