每天一种设计模式(一)-- 策略模式

目的:将对象和行为解耦。由继承得来的行为,灵活性不够,行为是写死在类中的。如果需要修改,
只能修改原来的类。如果修改超类,则所有子类都受影响。如果修改子类,那么子类中会出现大量
重复代码。比如有十个子类,它们的行为与超类行为不同,则要修改十个子类。问题是,这十个子
类的行为是一致的,却无法将行为重用。将行为抽离出来,则可以达到共用的目的。

  1. 只需要在对象中包含一个行为对象,调用行为对象的方法来完成对应行为即可。

  2. 行为对象要实现特定行为的接口。

比如一个Person对象,有吃饭,睡觉的行为。当然,你可以说人的吃和睡,能有什么差别。是的,大
部分人都是一样的。但是,有的人,就细嚼慢咽,有的人,则狼吞虎咽,对于一种行为来说,这确实是
有差别的。有的人睡觉很安静,有的人睡觉打呼噜,还的的人睡觉睁着眼睛,这也是差别。具体什么样
的差别算差别,还是业务逻辑说了算。

这时,最基本也是最直接的方式,就是在Person类中实现默认的,普遍的吃饭和睡觉方法。然后子类中
那些特别的人,去覆盖对应的方法。这时候,问题来了,有的人睡觉很安静,吃饭狼吞虎咽;有的人睡觉
很安静,吃饭细嚼慢咽;有的人睡觉打呼噜,吃饭狼吞虎咽。。。。对于这些拥有不同行为的人,要
创建它们的实例,就得根据行为不同,组合出各种不同的类,类爆炸来了。

public class Person {

	public void sleep() {
		System.out.println("普通人睡觉");
	}
	
	public void eat() {
		System.out.println("普通人吃饭");
	}
}
class Snorer extends Person{
	public void sleep() {
		System.out.println("呼噜。。。呼噜。。。");
	}
}

class Huger extends Person{
	public void eat() {
		System.out.println("狼吞虎咽");
	}
}

// 更多形形色色的组合

策略模式很好的解决了这个问题。
将睡觉,吃饭这些行为分离出去,不在是Person类的方法。而是单独的行为对象。行为对象只需要实现
行为接口。睡觉这个行为对象,实现了睡觉行为接口,假设为: interface Sleep 这个接口中,只有
一个方法, void sleep(); 很明显,行为对象实现此接口,只需要实现sleep方法即可。吃饭行为对象
也是一样。

现在行为对象有了,怎么和Person对象联系起来呢?

需要在Person类内部创建一个实例变量: Sleep sleepBehavior;
将以前硬编码在Person类内部的 sleep,eat方法做下修改。

interface Sleep{
  void sleep();
}
interface Eat{
  void eat();
}
public class SnorerSleep implements Sleep{
  System.out.println("呼噜。。。呼噜。。。");
}
public class HugerEat implements Eat{
  System.out.println("狼吞虎咽");
}
public abstract class Person{
	Sleep sleepBehavior;
	Eat eatBehavior;
	public void sleep(){
 		sleepBehavior.sleep();
	}
	public void eat(){
		eatBehavior.eat();
	}
}

public class Snorer extends Person{

  public Snorer(){
    this.sleepBehavior = new SnorerSleep();
  }
}

new Snorer().sleep(); // 呼噜。。。呼噜。。。

如果需要在运行时,动态的改变Person对象的行为,可以添加 sleepBehavior 和 eatBehavior 的setter
,调用之后,实例的行为就会发生变化。

这样,行为得到了复用,并且和对象解耦了。是不是更容易维护了?

缺点:

  1. 会产生很多策略类,但是相对原来的模式,要好很多。
  2. 需要了解所有的策略,才能作出正确的选择。但是,代码是咱们写的,这不是什么问题。有文档,更简单。
posted @ 2018-01-07 22:07  杯酒红尘  阅读(205)  评论(0编辑  收藏  举报