`
0428loveyu
  • 浏览: 29133 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

策略模式

阅读更多
许多情况下,在一个对象中完成某项任务存在有多种不同的策略。例如,有一个类Sorter对数组进行排序,排序的策略有很多种,实现不同策略排序的一种解决方案是通过类来继承。例如:
public class Sorter {

	public List<Object> sort(List<Object> listTobeSorted) {
		List<Object> sortedList = null;
		// do sort
		return sortedList;
	}

}

public class SorterA extends Sorter {
	public List<Object> sort(List<Object> listTobeSorted) {
		List<Object> sortedList = null;
		// do sort using strategy A
		return sortedList;
	}
}

public class SorterB extends Sorter {
	
        public List<Object> sort(List<Object> listTobeSorted) {
		List<Object> sortedList = null;
		// do sort using strategy B
		return sortedList;
	}
	
}


这些类之间的唯一区别是他们排序的策略不一样。另一种方式是为不同的排序策略定义单独的类,然后将这个类传递给Sorter,在Sorter中只需要根据这个策略来完成排序。

/**
 * 
 */
package design.patterns.strategy;

import java.util.List;

/**
 * @author Brandon B. Lin
 * 
 */
public class Sorter {

	private Comparator strategy;

	public Sorter(Comparator strategy) {
		this.strategy = strategy;
	}

	public void setStrategy(Comparator strategy) {
		this.strategy = strategy;
	}

	public List<Object> sort(List<Object> listTobeSorted) {
		List<Object> sortedList = null;
		// do sort using strategy
		return sortedList;
	}

}

public interface Comparator {
	public int compareTo(Object obaject, Object another);
}

public class ComparatorA implements Comparator {
	
	@Override
	public int compareTo(Object obaject, Object another) {
		return 0;
	}

}

public class ComparatorB implements Comparator {

	@Override
	public int compareTo(Object obaject, Object another) {
		// TODO Auto-generated method stub
		return 0;
	}

}
现在,我们可以使用Comparator对Sorter进行配置,以实现不同排序算法,事实上,我们甚至可以在程序运行的时候改变排序策略(通过setStrategy方法),这是继承无法做到的。当然,也可以将排序任务全部委托给策略,而在Sorter类中简单地调用策略的排序方法。



策略模式的类图如下:


下面是一个来自StackOverFlow的例子,实现不同的认证策略:

public class AuthenticationHandlerImpl implements AuthenticationHandler {

    private Authenticator authenticator;

    void authenticate() throws ConnectionException {
        authenticator.authenticate();
    };

    public void setAuthenticator(final Authenticator  authenticator){
        this.authenticator = authenticator;
    }

}

interface Authenticator {
    void authenticate();
    void setLogin(String login);
    void setPassword(String password);
}

class URLAuthenticator implements Authenticator {
    public void authenticate() {
        //use URLConnection
    };
}

class HTTPClientAuthenticator implements Authenticator {
    public void authenticate() {
        //use HTTPClient
    };
}

在Java API中,有许多地方都用到了策略模式。事实上java.util.Arrays提供的数组排序方法就用到了策略模式,其中一个方法声明如下:

 public static <T> void sort(T[] a, Comparator<? super T> c)
其中,传递的参数Comparator就是策略。


在Java Swing中,容器类的布局也是通过策略模式来实现的。比如,对于JFrame,可以通过setLayout(LayoutManager manager)来配置布局管理器,如果不这么做,我们可能就要继承JFrame来实现不同的布局,比如FlowJFrame实现流布局,GridJFrame实现网格布局。


在URL中,也用到了策略模式。对于不同协议的URL,如http,ftp,如何读取服务器返回的数据,必须遵循相应的协议。因此,通过策略URLStreamHandler来实现对不同协议的流内容的处理,URLStreamHandler根据协议产生相应的URLConnection,然后使用URLConnection读取数据流中的内容。只不过在这里,策略的Java自动帮我们完成,Java根据URL协议部分自动选择合适的URLStreamHandler来处理流,可以通过几成这个类来实现对自定义协议的支持。


策略模式与命令模式有着很微妙的区别。

策略对象可以采用工厂方法模式来创建,或者通过享元模式(Flyweight)来共享。





分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics