1. 使用模式最好的方式是:“把模式装进脑子里,然后在你的设计和已有的应用中,寻找何处可以使用它们。”
2. 设计原则1:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
a. E(explain): 把会变化的部分取出并“封装”起来,好让其他部分不会受到影响;
b. E: “把会变化的部分取出并封装起来,以便以后可以轻易地改动或扩充此部分,而不影响不需要变化的其他部分”;
c. 如果每次新的需求一来,都会使某方面的代码发生变化,那么你就可以确定,这部分的代码需要被抽出来,和其他稳定的代码有所区分。
3. Java接口不具有实现代码,所以继承接口无法达到代码的复用。这意味着:无论何时你需要修改某个行为,你必须得往下追踪并在每一个定义此行为的类中修改它,一不小心,可能会造成新的错误!
4. 干脆顺便让鸭子的行为可以动态地改变好了。换句话说,我们应该在鸭子类中包含设定行为的方法,这样就可以在“运行时”动态地“改变”绿头鸭的飞行行为;
5. 设计原则2: 针对接口编程,而不是针对实现编程。
a. E: “针对接口编程”真正的意思是“针对超类型(supertype)编程”;
b. E: “针对接口编程”,关键就在多态。利用多态,程序可以针对超类型编程,执行时会根据实际状况执行到真正的行为,不会被绑定在超类型的行为上。
c. E:“针对超类型(supertype)编程”这句话,可以更明确地说成“变量的声明类型应该是超类型,通常是一个抽象类或者是一个借口”。
6. 通常在设计系统时,预先考虑到有哪些地方未来可能需要变化,于是提前在代码中加入这些弹性。
7. Steps:
a. 首先,在Duck类中,“加入两个实例变量”,flyBehavior和quackBahavior,声明为接口类型;
b. 在perform中,通过行为变量调用行为;
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck() {
}
public void setFlyBehavior(FlyBehavior fb) {
flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb) {
quackBehavior = qb;
}
abstract void display();
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public void swim() {
System.out.println("All ducks float, even decoys!");
}
}
8. 动态设定行为:通过Setter方法;(代码见上面的Duck类);
a. 在运行时想改变鸭子的行为,只需调用鸭子的setter方法就可以;
9. 设计原则3:多用组合,少用继承;
a. 当将两个类结合起来使用(本例中的flyBehavior和quackBahavior),这就是组合(composition)。这种做法和“继承”不同的地方在于,鸭子的行为不是继承来的,而是和适当的行为对象“组合”来的;
b. 使用组合建立系统具有很大的弹性,不仅可将算法族封装成类,更可以“在运行时动态地改变行为”,只要组合的行为对象符合正确的接口标准即可;
10. 策略模式:定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户;
11. 库和框架提供了我们某些特定的实现,让我们的代码可以轻易地引用,但是这并不算是设计模式。库和框架本身会用到设计模式。一旦你了解了设计模式,会更容易了解这些API是围绕着设计模式构造的;
12. 大多数的模式和原则,都着眼于软件变化的主题。
DecoyDuck.java
package headfirst.designpatterns.strategy;
public class DecoyDuck extends Duck {
public DecoyDuck() {
setFlyBehavior(new FlyNoWay());
setQuackBehavior(new MuteQuack());
}
public void display() {
System.out.println("I'm a duck Decoy");
}
}
Duck.java
package headfirst.designpatterns.strategy;
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck() {
}
public void setFlyBehavior(FlyBehavior fb) {
flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb) {
quackBehavior = qb;
}
abstract void display();
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public void swim() {
System.out.println("All ducks float, even decoys!");
}
}
FakeQuack.java
package headfirst.designpatterns.strategy;
public class FakeQuack implements QuackBehavior {
public void quack() {
System.out.println("Qwak");
}
}
FlyBehavior.java
package headfirst.designpatterns.strategy;
public interface FlyBehavior {
public void fly();
}
FlyNoWay.java
package headfirst.designpatterns.strategy;
public class FlyNoWay implements FlyBehavior {
public void fly() {
System.out.println("I can't fly");
}
}
FlyRocketPowered.java
package headfirst.designpatterns.strategy;
public class FlyRocketPowered implements FlyBehavior {
public void fly() {
System.out.println("I'm flying with a rocket");
}
}
FlyWithWings.java
package headfirst.designpatterns.strategy;
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("I'm flying!!");
}
}
MallardDuck.java
package headfirst.designpatterns.strategy;
public class MallardDuck extends Duck {
public MallardDuck() {
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
public void display() {
System.out.println("I'm a real Mallard duck");
}
}
MiniDuckSimulator.java
package headfirst.designpatterns.strategy;
public class MiniDuckSimulator {
public static void main(String[] args) {
MallardDuck mallard = new MallardDuck();
RubberDuck rubberDuckie = new RubberDuck();
DecoyDuck decoy = new DecoyDuck();
Duck model = new ModelDuck();
mallard.performQuack();
rubberDuckie.performQuack();
decoy.performQuack();
model.performFly();
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
}
}
MiniDuckSimulator1.java
package headfirst.designpatterns.strategy;
public class MiniDuckSimulator1 {
public static void main(String[] args) {
Duck mallard = new MallardDuck();
mallard.performQuack();
mallard.performFly();
Duck model = new ModelDuck();
model.performFly();
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
}
}
ModelDuck.java
package headfirst.designpatterns.strategy;
public class ModelDuck extends Duck {
public ModelDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
public void display() {
System.out.println("I'm a model duck");
}
}
MuteQuack.java
package headfirst.designpatterns.strategy;
public class MuteQuack implements QuackBehavior {
public void quack() {
System.out.println("<< Silence >>");
}
}
Quack.java
package headfirst.designpatterns.strategy;
public class Quack implements QuackBehavior {
public void quack() {
System.out.println("Quack");
}
}
QuackBehavior.java
package headfirst.designpatterns.strategy;
public interface QuackBehavior {
public void quack();
}
RedHeadDuck.java
package headfirst.designpatterns.strategy;
public class RedHeadDuck extends Duck {
public RedHeadDuck() {
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
}
public void display() {
System.out.println("I'm a real Red Headed duck");
}
}
RubberDuck.java
package headfirst.designpatterns.strategy;
public class RubberDuck extends Duck {
public RubberDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new Squeak();
}
public void display() {
System.out.println("I'm a rubber duckie");
}
}
Squeak.java
package headfirst.designpatterns.strategy;
public class Squeak implements QuackBehavior {
public void quack() {
System.out.println("Squeak");
}
}