学习:设计模式之策略模式

来源:互联网 发布:淘宝店铺怎么加客服 编辑:程序博客网 时间:2024/05/19 16:33

本文来自www.lanttor.org



会飞的鸭子

经验

把模式装进你的脑子里,然后在你的设计和已有的应用里,寻找何处可以使用它们。以往是代码复用,现在是经验复用。

 

设计原则

找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。把会变化的部分取出并“封装”起来,让其他部分不会受到影响。结果如何?代码变化引起的不经意后果变少,系统变得更有弹性。

设计鸭子的行为

我们知道Duck类内的fly()和quack()会随着鸭子的不同而改变。

为了要把这两个行为从Duck类中分开,我们将把它们从Duck类中取出来,建立一组新类来代表每个行为。

从现在开始,鸭子的行为将被放在分开的类中,此类专门提供某行为接口的实现。

 

设计原则

针对接口编程,而不是针对实现编程。“这对接口编程”的真正意思是“针对超类型(supertype)编程”。更明确的说:变量的声明类型应该是超类型,通常是一个抽象类,或者是一个接口。如此,只要是具体实现此超类型的类所产生的对象,都可以指定给这个对象。这也意味着,声明类时不用理会以后执行的真正对象类型。

 

针对实现编程的例子(反面示例):

Dog d = new Dog();

d.bark()

 

针对接口编程的例子(正面示例):

Animal animal = new Dog();

Animal.makeSound();

 

更棒的例子(在运行时才指定具体实现的对象):

a = getAnimal();

a.makeSound();

 

 

为此,我们有两个接口,FlyBehavior和QuackBehavior,还有它们对应的类,负责实现具体的行为:

s1

整合鸭子的行为

关键在于,鸭子类现在会将飞行和呱呱叫的动作“委托”(delegate)别人处理,而不是使用定义在Duck类(或子类)内的呱呱叫和飞行方法。

 

1. 首先,在Duck类中加入两个实例变量,分别为"flyBehavior"和"quackBehavior",声明为接口类型。

s2

2. 现在,我们来实现performQuack():

s3

3. 设定flyBehavior与quackBehavior的实例变量。看看MallardDuck类:

s4

测试Duck的代码

Duck.java代码:

package headfirst.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!");

    }

}

 

 

FlyBehavior接口代码(FlyBehavior.java):

package headfirst.strategy;

public interface FlyBehavior {

    public void fly();

}

 

 

QuackBehavior接口代码(QuackBehavior.java):

package headfirst.strategy;

public interface QuackBehavior {

    public void quack();

}

 

 

MallarDuck.java代码:

package headfirst.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");

    }

}

 

 

Quack.java代码:

package headfirst.strategy;

public class Quack implements QuackBehavior {

    public void quack() {

        System.out.println("Quack");

    }

}

 

FlyWithWings.java代码:

package headfirst.strategy;

public class FlyWithWings implements FlyBehavior {

    public void fly() {

        System.out.println("I'm flying!!");

    }

}

 

ModelDuck.java代码:

package headfirst.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");

    }

}

 

FlyNoWay.java代码:

package headfirst.strategy;

public class FlyNoWay implements FlyBehavior {

    public void fly() {

        System.out.println("I can't fly");

    }

}

 

测试代码MiniDuckSimulator1.java:

package headfirst.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();

    }

}

 

FlyRocketPowered.java代码:

package headfirst.strategy;

public class FlyRocketPowered implements FlyBehavior {

    public void fly() {

        System.out.println("I'm flying with a rocket");

    }

}

 

运行测试结果

Quack

I'm flying!!

I can't fly

I'm flying with a rocket

 

总结

s5

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

设计原则多用组合,少用继承

 

本文的完整文档请参考"设计模式之策略模式.pdf“

 


0 0
原创粉丝点击