每天一个设计模式之strategy

上次讲到了template以及template和strategy的异同,所以今天我就看看strategy。

趁热打铁嘛~

 

回顾一下:

template和strategy pattern的共同之处就是,都是将代码中的算法/variant 的部分独立出来。

不同之处是

The strategy pattern is with Template Method pattern. The difference consists in the fact that Strategy uses delegation while the Template Methods uses the inheritance.

 

所以看strategy的重点应放在将代码可变部分独立出来,和delegation上。

 

那么,开始了~

 

motivation:

There are common situations when classes differ only in their behavior. For this cases is a good idea to isolate the algorithms in separate classes in order to have the ability to select different algorithms at runtime.

 

Intent:

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.


先来看一个例子:

有一个机器人类和一个main类。还有三个Behavior类,代表了三种不同的性格(算法),同时实现了一个接口IBehaviour。main中创建了3个机器人,每个机器人有自己的名字,同时通过setBehacior让他们性格不同,有的天生攻击性强,有的胆子小。这三个机器人被放到一个小舞台上,当他们相遇时,就会根据各自的位置,性格,产生不同的反应:攻击或逃跑,或假装没看见。之后可以通过修改每个机器人的性格,让他们产生不同的行为。

 

public interface IBehaviour {
	public int moveCommand();
}

public class AgressiveBehaviour implements IBehaviour{
	public int moveCommand()
	{
		System.out.println("\tAgressive Behaviour: if find another robot attack it");
		return 1;
	}
}

public class DefensiveBehaviour implements IBehaviour{
	public int moveCommand()
	{
		System.out.println("\tDefensive Behaviour: if find another robot run from it");
		return -1;
	}
}

public class NormalBehaviour implements IBehaviour{
	public int moveCommand()
	{
		System.out.println("\tNormal Behaviour: if find another robot ignore it");
		return 0;
	}
}

public class Robot {
	IBehaviour behaviour;
	String name;

	public Robot(String name)
	{
		this.name = name;
	}

	public void setBehaviour(IBehaviour behaviour)
	{
		this.behaviour = behaviour;
	}

	public IBehaviour getBehaviour()
	{
		return behaviour;
	}

	public void move()
	{
		System.out.println(this.name + ": Based on current position" +
					 "the behaviour object decide the next move:");
		int command = behaviour.moveCommand();
		// ... send the command to mechanisms
		System.out.println("\tThe result returned by behaviour object " +
					"is sent to the movement mechanisms " + 
					" for the robot '"  + this.name + "'");
	}

	public String getName() {
		return name;
	}

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


public class Main {

	public static void main(String[] args) {

		Robot r1 = new Robot("Big Robot");
		Robot r2 = new Robot("George v.2.1");
		Robot r3 = new Robot("R2");

		r1.setBehaviour(new AgressiveBehaviour());
		r2.setBehaviour(new DefensiveBehaviour());
		r3.setBehaviour(new NormalBehaviour());

		r1.move();
		r2.move();
		r3.move();

		System.out.println("\r\nNew behaviours: " +
				"\r\n\t'Big Robot' gets really scared" +
				"\r\n\t, 'George v.2.1' becomes really mad because" +
				"it's always attacked by other robots" +
				"\r\n\t and R2 keeps its calm\r\n");

		r1.setBehaviour(new DefensiveBehaviour());
		r2.setBehaviour(new AgressiveBehaviour());

		r1.move();
		r2.move();
		r3.move();
	}
}

这段代码充分体现了使用strtegy pattern的意图:

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. (前面提过了)

再对比一下template method。template 是定义了算法的框架,而具体的实现都在concrete类里,通过继承得到算法的框架。strtegy的特点则是算法完全独立于concrete类,且concrete类通过get/set取得算法。

 

Drawbacks:

 

由于通常concrete类需要传一些信息给strategy,如上面的机器人所在的位置,strategy再给出相应的reaction。因为会造成strategy和concrete类之间耦合度加强。

如果需要传送的信息比较复杂,比如位置,温度,矢量方向etc。可能需要新建额外的类来包含这些信息。这就需要考虑一个问题:哪些信息需要被传递,因为

1, 需要传递的信息在将来可能会发生变化。

2, 传递的信息对于某些算法来说可能是多余的。

 

另外,

The strategy design pattern splits the behavior (there are many behaviors) of a class from the class itself. This has some advantages, but the main draw back is that a client must understand how the Strategies differ.

 

使用技巧:

1,

算法与算法之间可以被定义的更复杂,而不仅仅和上例一样是都是平行结构,因此又可以引进更复杂的结构和模式:

The strategies can be defined as a hierarchy of classes offering the ability to extend and customize the existing algorithms from an application. At this point the composite design pattern can be used with a special care.

 

2,

在concrete class中可以定义默认算法,只有需要时才去调用外部strategy。

This is an elegant solution to exposing some customization points to be used only when they are required。

 

Strategy and Bridge的异同

Both of the patterns have the same UML diagram. But they differ in their intent since the strategy is related with the behavior and bridge is for structure. Further more, the coupling between the context and strategies is tighter that the coupling between the abstraction and implementation in the bridge pattern.

(前面提到过,耦合度较大是strategy的一个问题)

 

这里再说一点,关于dependency injection。

核心的思想就是,实际的逻辑是在运行/被调用时才决定的,而不是类本身决定的。A class should not configure itself but should be configured from outside.

 

比如strategy就是一个例子:上例中每个机器人的behavior是在被调用时才决定,而不是robot这个类决定的。且运行时可是随时改变behavior。实际的算法是在运行时被“inject”到concrete class中。就像面向接口的编程思想一样,目的都是为了灵活。

 

 

If dependency injection is used then the class B is given to class A via

  • the constructor of the class A - this is then called construction injection

  • a setter - this is then called setter injection

 

所以strategy是使用了setter的方法,将算法inject给了concrete类。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值