从今天开始,学习《深入浅出设计模式》这本书,并每看完一章就自己写些代码来加深理解,并把文中的一些知识写出来,和代码一起更新到博客里。(中文和英文版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),角色可以用不同的武器,但一次只能用一种武器,而且在游戏过程中可以更换武器。
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类图为:
鉴于篇幅,只贴部分代码,全部代码见附件:
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();
}
}
运行结果:
我是国王 拉弓,放箭
我是怪物 挥斧头
我是国王 出剑