`

《深入浅出设计模式》读书笔记--策略模式与三个设计原则

阅读更多

从今天开始,学习《深入浅出设计模式》这本书,并每看完一章就自己写些代码来加深理解,并把文中的一些知识写出来,和代码一起更新到博客里。(中文和英文版pdf,另找地址上传,建议英文版,比较清晰)

对于设计模式,先摘抄此书中文版的一句话: 信耶稣的人都要读圣经,而信 OO 的人都要读四人组的《设计模式》

另一句:使用模式的最好方式是:把模式装进脑子,然后在你的设计和已有的应用中,寻找何处可以使用它们。


在第一章,先是以一个模拟鸭子程序开始,一个Duck的父类,有很多个继承Duck类的具体鸭类。目前遇到这样的情况:  

1.       继承,不易知道所有鸭子的公共方法,在父类修改为牵连到所有子类,

 

第一版鸭子程序

 

2.       老板要求增加一个飞方法(fly())时,在父类增加,导致所有鸭子都可飞,有些是塑料鸭子也可以飞了,不妥;

3.      那不在父类增加fly()方法,而是把飞的方法抽象为一接口,让会飞的实体鸭类才实现该接口,但这又导致了重复代码的危险,因为每个实现飞接口的子类都要有相同的飞实现代码,万一以后又要对飞方法的修改,那就要对所有实现了飞接口的子类都修改,仍不妥;

 

4.       最后想出一个办法:增加 FlyBehavior 接口,其中接口中有一个方法,分别是 fly() ,并写相应实现接口的类。

 

 

其中Duck类里的performFly()方法代码(另增加一个设置该类飞行行为的方法setFlyBehavior() ):

	public void performFly() {
		flyBehavior.fly();
	}
	public void setFlyBehavior (FlyBehavior fb) {
		flyBehavior = fb;
	}

到这里,设计已经几乎完成了,如果要更改fly方法,只需增加一个实现FlyBehavior接口的方法,并调用setFlyBehavior,就可以在运行时动态地更改fly方法。

 

 

下面是 提到的设计原则,从上面的代码也可以体现出来:

一. 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。(把会变化的部分取出并“封装”起来,使得系统某部分的改变不会影响其它)。

二. 针对接口编程,而不是针对实现编程。

三. 多用组合,少用继承。

 

策略模式的定义:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户

 

接下来是为Design Puzzle里的设计的代码,背景是:

这是一个为动作冒险游戏而设计的程序,其中会用到角色类(Character),角色可以用不同的武器,但一次只能用一种武器,而且在游戏过程中可以更换武器。

背景英文原文 写道
Below you’ll fi nd a mess of classes and interfaces for an action adventure game. You’ll
fi nd classes for game characters along with classes for weapon behaviors the characters
can use in the game. Each character can make use of one weapon at a time, but can
change weapons at any time during the game. Your job is to sort it all out...
 

下面直接贴出答案,自己可以先思考一下。

UML类图为:

character_uml

 

 

鉴于篇幅,只贴部分代码,全部代码见附件:

package chow.hfdp.chapter1.designPuzzle;

//  Generated by StarUML(tm) Java Add-In
//
//  @ Project : Untitled
//  @ File Name : Character.java
//  @ Date : 2011/9/3
//  @ Author : bosshida
//
//

public abstract class Character {
	public WeaponBehavior weapon;
	public void setWeapon(WeaponBehavior weapon){
		this.weapon = weapon;
	}
	
	public abstract void fight();
}
 
package chow.hfdp.chapter1.designPuzzle;

//  Generated by StarUML(tm) Java Add-In
//
//  @ Project : Untitled
//  @ File Name : King.java
//  @ Date : 2011/9/3
//  @ Author : bosshida
//
//

public class King extends Character {
	public void fight() {
		System.out.print("我是国王 ");
		weapon.useWeapon();
	}
}

 

package chow.hfdp.chapter1.designPuzzle;

//  Generated by StarUML(tm) Java Add-In
//
//  @ Project : Untitled
//  @ File Name : WeaponBehavior.java
//  @ Date : 2011/9/3
//  @ Author : bosshida
//
//

public interface WeaponBehavior {
	public void useWeapon();
}
 
package chow.hfdp.chapter1.designPuzzle;

//  Generated by StarUML(tm) Java Add-In
//
//  @ Project : Untitled
//  @ File Name : SwordBehavior.java
//  @ Date : 2011/9/3
//  @ Author : bosshida
//
//

public class SwordBehavior implements WeaponBehavior {
	public void useWeapon() {
		System.out.println("出剑");
	}
}

 

package chow.hfdp.chapter1.designPuzzle;

/**
 * 这是一个为动作冒险游戏而设计的程序,其中会用到角色类(Character),角色可以用不同的武器<br>
 * 但一次只能用一种武器,而且在游戏过程中可以更换武器。这时用到策略模式,并遵守三种设计原则:<br>
 * 1.独立变化并封装(武器更换作为一种Behavior);2.针对接口编程,不是针对实现编程(WeaponBehavior)<br>
 * 为一接口);3.多用组合,少用继承(在Character类里,组合一个weapon对象) <br>
 * 策略模式定义:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化<br>
 * 独立于使用算法的客户(这里是对使用武器不同而封装)
 * @author bosshida
 * @date 2011-9-3
 */
public class Main {
	public static void main(String[] args) {
		Character king = new King();
		Character troll = new Troll();
		
		king.setWeapon(new BowAndArrowBehavior());
		troll.setWeapon(new AxeBehavior());
		
		king.fight();
		troll.fight();
		
		king.setWeapon(new SwordBehavior());
		king.fight();
	}
}

 

运行结果:

我是国王 拉弓,放箭
我是怪物 挥斧头
我是国王 出剑

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics