Java与设计模式(06)--策略模式

定义


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


角色

  1. Strategy接口:定义了算法的形式;
  2. ConcreteStrategy:实现了具体算法;
  3. Context:对接口中的算法进行实用;
  4. Client:测试类;


实际使用

这里我们可以看个例子:


例子一:

我们有一个这样的类:

package com.freesoft.designpattern.strategy;

public class Person {
	private int id;
	private String name;
	
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}


}

有一天我们想对这个类组成的集合对象进行排序,那么必须要有一个手段能够对这个类的对象进行比较,所以我们这样实现:

package com.freesoft.designpattern.strategy;

public class Person implements Comparable<Person> {
	private int id;
	private String name;
	
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public int compareTo(Person o) {
		if (this.getId() != o.getId()) {
			Integer id1 = Integer.valueOf(this.getId());
			Integer id2 = Integer.valueOf(o.getId());
			return  id1.compareTo(id2);
		} else {
			String name1 = this.getName();
			String name2 = o.getName();
			return name1.compareTo(name2);
		}
	}
}

通过以上实现,我们能够对Person类型的两个对象实现比较操作,首先比较id,如果id相同那么比较name字段。在集合中我们可以根据这个规则(策略)来对集合进行排序。


问题来了,我们不能保证这个规则/策略就是我们需要的策略。比如,我们可能需要先比较name字段,或者我们可能在某种情况下使用id优先原则,某种情况下使用name优先原则,所以我们的策略是会变化的


考虑到以上问题,我们需要修改我们的代码,我们单独编写一个策略类:

package com.freesoft.designpattern.strategy;

import java.util.Comparator;

public class PersonComparatorById implements Comparator<Person> {
	@Override
	public int compare(Person o1, Person o2) {
		if (o1.getId() != o2.getId()) {
			Integer id1 = Integer.valueOf(o1.getId());
			Integer id2 = Integer.valueOf(o2.getId());
			return  id1.compareTo(id2);
		} else {
			String name1 = o1.getName();
			String name2 = o2.getName();
			return name1.compareTo(name2);
		}
	}
}

并且我们的Person代码变为:


package com.freesoft.designpattern.strategy;

import java.util.Comparator;

public class Person implements Comparable<Person> {
	private int id;
	private String name;
	private Comparator<Person> c;
	
	public Person(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	public Comparator<Person> getC() {
		return c;
	}

	public void setC(Comparator<Person> c) {
		this.c = c;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public int compareTo(Person o) {
		return c.compare(this, o);
	}
}

这样如果我们今后需要使用name优先的比较原则,我们只需要实现一个新类:

package com.freesoft.designpattern.strategy;

import java.util.Comparator;

public class PersonComparatorByName implements Comparator<Person> {
	@Override
	public int compare(Person o1, Person o2) {
		if (o1.getName().equals(o2.getName())) {
			Integer id1 = Integer.valueOf(o1.getId());
			Integer id2 = Integer.valueOf(o2.getId());
			return  id1.compareTo(id2);
		} else {
			String name1 = o1.getName();
			String name2 = o2.getName();
			return name1.compareTo(name2);
		}
	}
}

我们的测试类如下:


package com.freesoft.designpattern.strategy;

public class Client {
	public static void main(String[] args) {
		Person p1 = new Person(10, "zhangsan");
		Person p2 = new Person(20, "lisi");
		
		PersonComparatorById cId = new PersonComparatorById();
		PersonComparatorByName cName = new PersonComparatorByName();
		
		p1.setC(cId);
		System.out.println("p1 compara p2 by Id: " + p1.compareTo(p2));
		p1.setC(cName);
		System.out.println("p1 compara p2 by Name: " + p1.compareTo(p2));
	}
}



总结

  1. 我们的Comparator接口就是我们抽象的策略;
  2. 我们实现的一个个的PersonComparatorByXXX就是具体的策略;
  3. Person提供了比较的功能,但实际使用时通过setC传入不同的比较策略,所以在实际使用中非常灵活,并且可以独立单元测试、代码维护成本极低。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值