首发地址:http://www.cnblogs.com/syxchina/archive/2011/10/11/2207017.html
策略模式是一个很简单的模式,也是一个很常用的模式,可谓短小精悍,类库有很多使用策略模式的例子,所以本文以模拟类库为模板,学习策略模式,也熟悉了java类库设计中的精华,加深了我们的OO思想。
1 概念
策略模式(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.)
2 模拟java类库中Comparable和Comparator接口
本文实现一个简单的排序算法,通过一步步设计,设计Comparable和Comparator接口,理解了策略模式和java类库设计这2个接口的原因和不同用途。
3 最简单的排序例子
public class Test {
public static void main(String[] args) {
int[] nums = { 3, 4, 1, 5, 2 };
DataSortor.sort(nums);
DataSortor.p(nums);
}
}
class DataSortor {
public static void sort(int[] nums) {
for (int i = 0; i < nums.length; i += 1) {
for (int j = i + 1; j < nums.length; j += 1) {
if (nums[i] > nums[j]) {
nums[i] = nums[i] + nums[j];
nums[j] = nums[i] - nums[j];
nums[i] = nums[i] - nums[j];
}
}
}
}
public static void p(int[] nums) {
for (int i : nums) {
System.out.print(i + " ");
}
System.out.println();
}
}
一个最简单使用冒泡的排序一个int数组,优点简单明了,缺点扩展性和代码重用性不强(不考虑算法本身,比如什么样的数据用不用的排序算法),而且支持的类型单一!
4 支持多重类型的排序算法
public class Test {
public static void main(String[] args) {
int[] nums = { 3, 4, 1, 5, 2 };
DataSortor.sort(nums);
DataSortor.p(nums);
double[] doubles = { 1.2, 0.3, 2.5, 8.9, 0};
DataSortor.sort(doubles);
DataSortor.p(doubles);
Dog[] dogs = {new Dog(3,3), new Dog(1,1), new Dog(5,5)};
DataSortor.sort(dogs);
DataSortor.p(dogs);
}
}
class DataSortor {
public static void sort(int[] nums) {
for (int i = 0; i < nums.length; i += 1) {
for (int j = i + 1; j < nums.length; j += 1) {
if (nums[i] > nums[j]) {
nums[i] = nums[i] + nums[j];
nums[j] = nums[i] - nums[j];
nums[i] = nums[i] - nums[j];
}
}
}
}
public static void p(Dog[] dogs) {
for(int i=0; i<dogs.length; i+=1) {
System.out.print(dogs[i] + " ");
}
System.out.println();
}
public static void sort(Dog[] dogs) {
for (int i = 0; i < dogs.length; i += 1) {
for (int j = i + 1; j < dogs.length; j += 1) {
if (dogs[i].getHeight()>dogs[j].getHeight()) {
Dog temp = dogs[i];
dogs[i] = dogs[j];
dogs[j] = temp;
}
}
}
}
public static void p(double[] doubles) {
for (double i : doubles) {
System.out.print(i + " ");
}
System.out.println();
}
public static void sort(double[] doubles) {
for (int i = 0; i < doubles.length; i += 1) {
for (int j = i + 1; j < doubles.length; j += 1) {
if (doubles[i] > doubles[j]) {
doubles[i] = doubles[i] + doubles[j];
doubles[j] = doubles[i] - doubles[j];
doubles[i] = doubles[i] - doubles[j];
}
}
}
}
public static void sort1(int[] nums) {
for (int i = nums.length - 1; i >= 0; i -= 1) {
for (int j = 0; j < i; j += 1) {
if (nums[j] > nums[j+1]) {
nums[j+1] = nums[j+1] + nums[j];
nums[j] = nums[j+1] - nums[j];
nums[j+1] = nums[j+1] - nums[j];
}
}
}
}
public static void p(int[] nums) {
for (int i : nums) {
System.out.print(i + " ");
}
System.out.println();
}
}
class Dog {
private int height;
private int weight;
public Dog(int height, int weight) {
super();
this.height = height;
this.weight = weight;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
@Override
public String toString() {
return "Dog(" + height + "," + weight +")";
}
}
输出结果:
1 2 3 4 5
0.0 0.30000000000000004 1.2000000000000002 2.5 8.9
Dog(1,1) Dog(3,3) Dog(5,5)
添加了更多基本类型的排序和基本类的比较,但也扩展性和重用性差还是很差。
如果我们继续添加新的类,我们必须重新写比较方法,重新改我们的排序代码,排序算法不能得到重用!所以我们可以添加比较接口!
5 引入Comparable接口
public class Test {
public static void main(String[] args) {
Dog[] dogs = { new Dog(3, 3), new Dog(1, 1), new Dog(5, 5) };
DataSortor.sort(dogs);
DataSortor.p(dogs);
}
}
class DataSortor {
public static void p(Object[] objs) {
for (int i = 0; i < objs.length; i += 1) {
System.out.print(objs[i] + " ");
}
System.out.println();
}
public static void sort(Comparable[] objs) {
for (int i = 0; i < objs.length; i += 1) {
for (int j = i + 1; j < objs.length; j += 1) {
if (objs[i].compareTo(objs[j])>0) {
Comparable temp = objs[i];
objs[i] = objs[j];
objs[j] = temp;
}
}
}
}
}
interface Comparable {
int compareTo(Object obj);
}
class Dog implements Comparable {
private int height;
private int weight;
public Dog(int height, int weight) {
super();
this.height = height;
this.weight = weight;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
@Override
public String toString() {
return "Dog(" + height + "," + weight + ")";
}
@Override
public int compareTo(Object obj) {
if (obj instanceof Dog) {
Dog d = (Dog) obj;
if (height > d.getHeight())
return 1;
else
return -1;
}
return 0;
}
}
实现了Comparable接口的类,都可以使用排序算法,而不需要更改算法代码!提高的可用性,据有很大的扩展性。
但实现Comparable接口实现比较方法不能解决使用其他比较策略比较大小,比如上面使用cat的height作为比较依据,可能以后使用cat的weight作为比较依据。所以我们提出了策略模式,引入了Comparator接口,可以让cat选择比较策略,来实现不同的比较方法。
6 引入Comparator接口
public class Test {
public static void main(String[] args) {
Dog[] dogs = { new Dog(3, 3), new Dog(1, 1), new Dog(5, 5) };
DataSortor.sort(dogs);
DataSortor.p(dogs);
}
}
class DataSortor {
public static void p(Object[] objs) {
for (int i = 0; i < objs.length; i += 1) {
System.out.print(objs[i] + " ");
}
System.out.println();
}
public static void sort(Comparable[] objs) {
for (int i = 0; i < objs.length; i += 1) {
for (int j = i + 1; j < objs.length; j += 1) {
if (objs[i].compareTo(objs[j]) > 0) {
Comparable temp = objs[i];
objs[i] = objs[j];
objs[j] = temp;
}
}
}
}
}
interface Comparable {
int compareTo(Object obj);
}
interface Comparator {
int compare(Object o1, Object o2);
}
class DogHeightComparator implements Comparator {
@Override
public int compare(Object o1, Object o2) {
if (!(o1 instanceof Dog))
return 0;
if (!(o2 instanceof Dog))
return 0;
Dog dog1 = (Dog) o1;
Dog dog2 = (Dog) o2;
if (dog1.getHeight() > dog2.getHeight())
return 1;
else if (dog1.getHeight() < dog2.getHeight())
return -1;
return 0;
}
}
class Dog implements Comparable {
private int height;
private int weight;
private Comparator comparator = new DogHeightComparator();
@Override
public String toString() {
return "Dog(" + height + "," + weight + ")";
}
@Override
public int compareTo(Object obj) {
return comparator.compare(this, obj);
}
public Dog(int height, int weight) {
super();
this.height = height;
this.weight = weight;
}
public Comparator getComparator() {
return comparator;
}
public void setComparator(Comparator comparator) {
this.comparator = comparator;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
这样可以设计不同的Comparator来实现不同的比较方式,大大的提高了程序的扩展性,但值得说的类也要实现Comparable接口,只是在Comparable接口的实现方法中使用我们自己设置的排序策略,当然我们可以指定默认的排序算法,如上,这样如果有特殊需求时,在设置相应的排序算法,极大的提高了系统的灵活性。
现在,应该对策略模式有点较深的认识了吧,知道了为什么java类库中为什么有了Comparable还有Comparator接口了吧。
7 策略模式优缺点
优点:
1、 简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
缺点:
1、 因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。
2、
在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象。(这本身没有解除客户端需要选择判断的压力,而策略模式与简单工厂模式结合后,选择具体实现的职责也可以由Context来承担,这就最大化的减轻了客户端的压力。)
8 简单工厂模式和策略模式区别(摘录,出处)
这两种模式的作用就是拥抱变化,减少耦合。在变化来临时争取做最小的改动来适应变化。这就要求我们把些“善变”的功能从客户端分离出来,形成一个个的功能类,然后根据多态特性,使得功能类变化的同时,客户端代码不发生变化。
简单工厂模式
简单工厂模式:有一个父类需要做一个运算(其中包含了不同种类的几种运算),将父类涉及此运算的方法都设成虚方法,然后父类派生一些子类,使得每一种不同的运算都对应一个子类。另外有一个工厂类,这个类一般只有一个方法(工厂的生成方法),这个方法的返回值是一个超类,在方法的内部,根据传入参数的不同,分别构造各个不同的子类的对象,并返回。客户端并不认识子类,客户端只认识超类和工厂类。每次客户端需要一中运算时,就把相应的参数传给工厂类,让工厂类构造出相应的子类,然后在客户端用父类接收(这里有一个多态的运用)。客户端很顺理成章地用父类的计算方法(其实这是一个虚方法,并且已经被子类特化过了,其实是调用子类的方法)计算出来结果。如果要增加功能时,你只要再从父类中派生相应功能的子类,然后修改下工厂类就OK了,对于客户端是透明的。
策略模式
策略模式:策略模式更直接了一点,没有用工厂类,而是直接把工厂类的生成方法的代码写到了客户端。客户端自己构造出了具有不同功能的子类(而且是用父类接收的,多态),省掉了工厂类。策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。这里的算法家族和简单工厂模式里的父类是同一个概念。当不同的行为堆砌在一个类中时,就很难避免使用条件语句来选择合适的行为,将这些行为封装在一个个独立的策略子类中,可以在客户端中消除条件语句。
简单工厂模式+策略模式:为了将工厂方法的代码从客户端移出来,我们把这些代码搬到了父类的构造函数中,让父类在构造的时候,根据参数,自己实现工厂类的作用。这样做的好处就是,在客户端不用再认识工厂类了,客户端只要知道父类一个就OK,进一步隔离了变化,降低了耦合。
在基本的策略模式中,选择所用具体实现的职责由客户端对象成端,并转给客户端。这本身并没有减除客户端需要选择判断的压力,而策略模式与简单工厂模式结合后,选择具体实现的职责也可以由父类承担,这就最大化地减轻了客户端的职责。
9 总结
策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。
10参考资料
维基百科:策略模式
博客园:策略模式:ColinSong
简单工厂模式和策略模式区别:崔玉松
作者:syxChina
出处:http://syxchina.cnblogs.com、 http://hi.baidu.com/syxcs123
本文版权归作者、博客园和百度空间共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则作者会诅咒你的。
分享到:
相关推荐
例如,代理模式(Proxy Pattern)、单例模式(Singleton Pattern)、工厂方法模式(Factory Method Pattern)、抽象工厂模式(Abstract Factory Pattern)、适配器模式(Adapter Pattern)、模板方法模式(Template ...
处理对象的多种状态及其相互转换——状态模式(五) 处理对象的多种状态及其相互转换——状态模式(六) 策略模式-Strategy Pattern 算法的封装与切换——策略模式(一) 算法的封装与切换——策略模式(二) 算法的...
综上所述,策略模式在Java编程中是一个非常实用的设计模式,通过将算法封装到独立的策略类中,可以有效地管理和切换不同的行为,从而提升代码的灵活性和可维护性。在压缩包文件"StrategyPatterns例子"中,你可以找到...
总结来说,策略模式在Java和Android开发中是一种非常实用的设计模式,它通过封装不同的策略,使程序能够根据需要在运行时灵活选择和切换算法,提高了代码的灵活性和可扩展性。理解和掌握策略模式对于提升Android开发...
设计模式(22)-Strategy Pattern 设计模式(21)-Template Method Pattern 设计模式(20)-Visitor Pattern 设计模式(19)-Observer Pattern 设计模式(18)-Command Pattern 设计模式(17)-Chain of ...
在这个名为"JAVA design pattern-java设计模式"的CHM文件中,我们可能找到了关于如何在Java开发中应用设计模式的详细信息。 设计模式通常分为三大类:创建型、结构型和行为型。创建型模式关注对象的创建,如单例...
c++设计模式-行为型模式-策略模式;qt工程;c++简单源码; 策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于...
包括责任链模式(Chain of Responsibility)、命令模式(Command)、解释器模式(Interpreter)、迭代器模式(Iterator)、中介者...策略模式(Strategy)、模板方法模式(Template Method)和访问者模式(Visitor)...
行为型模式如观察者模式(Observer)、策略模式(Strategy)和访问者模式(Visitor),关注对象之间的交互和责任分配。 在C++中,设计模式的应用通常涉及到面向对象编程的特性,如继承、封装和多态。Qt4框架则为...
在这个“java设计模式-策略模式”的示例中,我们将深入探讨如何使用策略模式来实现一个简单的超市促销系统。 策略模式的核心思想是定义一系列的算法,并将每一个算法封装起来,使它们可以互相替换。这使得算法的...
行为型模式如策略(Strategy)、观察者(Observer)、访问者(Visitor)和模板方法(Template Method),关注对象之间的交互和职责分配。 在Java中,设计模式的应用广泛且深入。例如,单例模式在系统配置、线程池等...
策略模式是Java设计模式中的一种行为模式,它允许在运行时选择算法或策略,从而提供了更大的灵活性。在HeadFirst的《设计模式》一书中,第一章深入浅出地讲解了这一模式,通过实例帮助读者理解其核心概念和应用场景...
本资源“设计模式--java版.rar”提供了一种深入理解和应用Java设计模式的方式。 在Java开发中,设计模式主要分为三大类:创建型模式、结构型模式和行为型模式。创建型模式如单例(Singleton)、工厂方法(Factory ...
在众多的设计模式中,策略模式(Strategy Pattern)是一种行为设计模式,它使你能在运行时改变对象的行为。在这个“JAVA设计模式例程-策略模式”的压缩包中,我们可以深入探讨策略模式的原理及其应用。 策略模式的...
策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。这种模式允许你使用算法族,而无需在代码中硬编码这些算法。通过将算法封装到具有共同接口的独立对象中,策略模式使得你可以根据需要灵活地切换算法,...
行为型模式如策略(Strategy)、模板方法(Template Method)、观察者(Observer)、命令(Command)、迭代器(Iterator)、访问者(Visitor)、备忘录(Memento)、状态(State)、职责链(Chain of Responsibility...
策略模式(Strategy)是软件设计模式中的一种行为模式,它使你能在运行时改变对象的行为。在Java中,策略模式通常涉及定义一系列算法,并将每个算法封装起来,使得它们可以相互替换,同时使得算法的变化独立于使用它...
总结来说,Java设计模式中的策略模式是一种非常实用的设计模式,它允许我们在运行时选择和改变算法,提高了代码的可维护性和灵活性。通过观看厉风行老师的教程,你可以深入理解策略模式的原理,并将其运用到实际项目...
Java 策略模式详解 策略模式是一种行为型设计模式,它允许您定义一系列算法,将每个算法封装起来,并使它们可以互换使用。这种模式使得算法可以独立于使用它们的客户端而变化。在 Java 中,策略模式通常由一个接口...
策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。在软件开发中,我们经常遇到需要根据不同的条件或场景来执行不同算法的情况。策略模式提供了一种将算法族封装到各自独立的类中,并在运行时选择具体...