设计模式学习——策略模式Strategy

本文深入探讨了策略模式的概念、UML图示及具体应用场景,包括一个趣味性的例子和Java集合框架中的应用实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 杂言:

    好久没更新博客了,个人毅力问题。其实回想起来,如果那时就完成了24种设计模式的学习。这时候应该算是复习了。而且对设计模式的了解应该更上一层楼才对。所以逝者如斯夫,不舍昼夜。年轻人应该好好珍惜时光。话说,对于设计模式,很多人讲这种东西懂几个基础就好了,可能以后还用不上。其实这个问题,就好像我在大学学自动化时,问老师,我们这种学单片机的,干嘛学网络技术这种以后可能用不上的东西?老师说,学的东西总是潜默移化的影响着你。确实,像我这种爱好画画,平时偶尔看看文科类的书,大学学自动化,出来做IT行业的人来说。学东西,应当犹如韩信点兵,多多益善。

2. 理论:

    它定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法的变化不会影响到使用算法的客户。(原文: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.)

3. UML图:

  

原图


我画的类图


4. 举例:

    在写这篇文章前百度过一些别 人的例子,好像大多喜欢举一些鸡鸭猪狗之类的例子来说明。感觉这样很容易误导人,以为策略模式是创建型模式。其实策略模式是行为型模式。它关注的是对象的行为,而不是对象的创建。

  a. 遇到问题

    一天,一个博士发明了一台机器,能通过输入两个人的名字进行计算得出谁更帅,谁人品更好,谁更长寿。这台机器很快引起了村子的轰动。人们纷纷跑过来玩。一次5毛,博士很快成为了村子的高富帅。完毕。下面我们来瞧瞧这台神秘机器怎么实现的。

  b.代码实现

首先实现接口,定义统一方法。

package prov.sue.design.strategy;

public interface IStrategy {
	
	public void compare(String name1,String name2);

}

然后便是谁更帅的实现算法

package prov.sue.design.strategy;

public class HandsomeStrategy implements IStrategy {

	@Override
	public void compare(String name1, String name2) {
		// TODO Auto-generated method stub
           System.out.println(name1+"更帅");
	}

}

谁人品更好算法

package prov.sue.design.strategy;

public class LuckStrategy implements IStrategy {

	@Override
	public void compare(String name1, String name2) {
		// TODO Auto-generated method stub
		 System.out.println(name1+"人品更好");
	}

}


谁更长寿算法

package prov.sue.design.strategy;

public class LongevityStrategy implements IStrategy{

	@Override
	public void compare(String name1, String name2) {
		// TODO Auto-generated method stub
		 System.out.println(name1+"更长寿");
	}

}

环境角色,也就是这台机器了

package prov.sue.design.strategy;

public class CompareContext {
	
	private IStrategy iStrategy;
	
	
	public void compareHandsome(String name1,String name2)
	{
		iStrategy=new HandsomeStrategy();
		iStrategy.compare(name1, name2);
	}
	
	public void compareLuck(String name1,String name2)
	{
		iStrategy=new LuckStrategy();
		iStrategy.compare(name1, name2);
	}
	
	
	public void compareLongevity(String name1,String name2)
	{
		iStrategy=new LongevityStrategy();
		iStrategy.compare(name1, name2);
	}

}

最后,看看怎么使用这个机器。

package prov.sue.design;

import prov.sue.design.strategy.CompareContext;

public class DesignMain {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		CompareContext context=new CompareContext();
		context.compareHandsome("小明", "小东");
		context.compareLuck("小明", "小东");
		context.compareLongevity("小明", "小东");
	}

}


小明和小东大战3回合,终于得出了结论

小明更帅
小明人品更好
小明更长寿

好吧,小东别哭,可能小明女朋友没你多。


5. 应用实例:

在Java的集合框架中,构造Map或者Set时传入Comparator比较器,或者创建比较器传入Collections类的静态方法中作为方法的参数为Collection排序时,都使用到了策略模式

下面就以创建比较器传入Collections类的静态方法为例说明,下面是简单的调用代码:
LinkedList<String> list = new LinkedList<String>();
list.add("arthinking");
list.add("Jason");
list.add("X");
//创建一个逆序的比较器
Comparator<String> r = Collections.reverseOrder();
//通过逆序的比较器进行排序
Collections.sort(list,r);

使用Collections.reverseOrder()方法床架一个比较器之后,再调用Collections.sort(list, r)把比较器传入该方法中进行排序,下面就看一下sort(list, r)中的代码:

public static <T> void sort(List<T> list, Comparator<? super T> c) {
	Object[] a = list.toArray();
	Arrays.sort(a, (Comparator)c);
	ListIterator i = list.listIterator();
	for (int j=0; j<a.length; j++) {
	    i.next();
	    i.set(a[j]);
	}
}

Arrays.sort(a, (Comparator)c);这句继续把比较器传入处理,下面是Arrays.sort(a, (Comparator)c)的具体操作:

public static <T> void sort(T[] a, Comparator<? super T> c) {
	T[] aux = (T[])a.clone();
        if (c==null)
            mergeSort(aux, a, 0, a.length, 0);
        else
            mergeSort(aux, a, 0, a.length, 0, c);
}

这里又调用了mergeSort(aux, a, 0, a.length, 0, c);继续传递比较器,再跟进去,发现如下执行代码:

private static void mergeSort(Object[] src,
				  Object[] dest,
				  int low, int high, int off,
				  Comparator c) {
	int length = high - low;

	// Insertion sort on smallest arrays
	if (length < INSERTIONSORT_THRESHOLD) {
	    for (int i=low; i<high; i++)
		for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
		    swap(dest, j, j-1);
	    return;
	}

        // Recursively sort halves of dest into src
        int destLow  = low;
        int destHigh = high;
        low  += off;
        high += off;
        int mid = (low + high) >>> 1;
        mergeSort(dest, src, low, mid, -off, c);
        mergeSort(dest, src, mid, high, -off, c);

        // If list is already sorted, just copy from src to dest.  This is an
        // optimization that results in faster sorts for nearly ordered lists.
        if (c.compare(src[mid-1], src[mid]) <= 0) {
           System.arraycopy(src, low, dest, destLow, length);
           return;
        }

        // Merge sorted halves (now in src) into dest
        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
}

这段代码有点复杂,我们跳出其中使用到比较器的代码分析:

c.compare(dest[j-1], dest[j])>0;

这里的compare方法在Comparator接口中也有定义:

public interface Comparator<T> {
    int compare(T o1, T o2);
}

由于这里使用泛型实现了Comparator,所以实际执行时,会根据比较器的具体实现类调用到实现代码,也就是上面创建的逆序比较器的compare方法,其实现如下:

public int compare(Comparable<Object> c1, Comparable<Object> c2) {
     return c2.compareTo(c1);
}
从上面的跟踪代码执行流程,可以得出:

抽象策略角色类为:Comparator接口
真实策略角色类为:ReverseComparator
我们在这里传入不同的比较器就会得到不同的排序的执行方法了:

Collections.sort(list,r);
除了文章中有特别说明,均为IT宅原创文章,转载请以链接形式注明出处。
本文链接: http://www.itzhai.com/java-source-code-analysis-strategy-pattern-implementation-in-java-collections-framework-embodied-in-the-code.html


6. 探讨 无




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值