Strategy Pattern(策略模式)

来源:互联网 发布:恢复数据库删除的数据 编辑:程序博客网 时间:2024/04/30 05:00

         学习Object Oriented(OO)也有段时间了,但一直没有学习Pattern Design方面的东西,感觉使用OO的时候完全不给力啊。So, balabala........

          Sorry,扯了一点废话。

          Strategy Pattern,在WikiPedia中解释为:a particularsoftware design pattern, whereby algorithms can be selected at runtime. 也就是说,Strategy Pattern在运行时能够改变算法的一种设计模式。那么,这个算法是什么呢?这里的算法,指的是Object的行为,比如一个Duck,它拥有Fly的行为,但是运行时改变算法,使其can't Fly。这就是Strategy Pattern的优势所在。当然,《Head First 设计模式》中对它也有定义:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

           OK,我们以《Head First 设计模式》中的例子来说明。

               我们要设计以下两个类,MallarDuck(绿头鸭)和RedheadDuck(红头鸭)。既然都是Duck(鸭),会OO的人都会想到--inherit(继承)。那这两种鸭子有什么共有的特性,我们可以将它们抽象出来放入一个父类Duck中呢。哦,它们都会quack,还有swim!于是,有了下面的设计:


            嗯,看起来不错的样子。但是过了一天,老板(产品经理,又或者其他**,你明白的)说,我们要新的功能,MallardDuck和RedheadDuck都要有fly( )的行为!嗯,不怕,OO的好处来了。只要在Duck类中新加入fly( )行为,这下所有的子类都有fly( )的行为了,一切OK!

            等等,让我想想,真的OK吗?第3天,**(who?)又说,我们仅有MallardDuck与RedheadDuck太少了,我们需要一个RubberDuck ! OK,so easy。

            Hold on !   RubberDuck好像不会飞啊。但是为什么RubberDuck有fly( )这个行为!那也行,好吧,在RubberDuck中覆盖fly( )方法,但是什么也不做吧。


class RubberDuck extend Duck {        ......        @override        public fly() {                 // do nothing        }        ......}

           看上去还成。但是如果不止增加RubberDuck呢,还有ModelDuck, 以及**Duck, balabala........那不是每个类都要覆盖fly( )方法?你怎么知道只有fly( )方法。要是**Duck不会swim呢(我们假设有这样一种Duck)?OMG,我的OO呢,说好的方便呢?

           嘿,谁说没有好方法。且看:

 

            这下,谁看要什么方法就让它有吧,想要fly( )方法,就实现Flyable这个接口;想要quack方法,就实现Quackable接口。Oh, No !   这不是N多代码重复吗!MallardDuck与RedheadDuck的fly( )方法是一样的啊,说好的代码复用呢?

            等等,好像灵感又来了!代码复用?参考Duck类的做法不就行了!

                   Oh, 终于告一段落了,这样就可以了!再等等!什么,还有?!学习OO的时候,前人都告诫说:少用继承,多用组合。似乎继承过多了。。。还是多重的。。。那再修改!

               这么修改,还增加了一个功能:运行时可以替换Object的行为啊,组合果然是个good choice !

               其实,最后一个版本就是刚开始就提到的Strategy Pattern, 真是“千呼万唤始出来”啊。


              另外,附上最终的Java代码,让我们更好的理解它。


Duck.java:

// Duck.javapublic abstract class Duck {FlyBehavior flyBehavior;QuackBehavior quackBehavior;public Duck() {}public abstract void display();public void performFly(){flyBehavior.fly();}public void performQuack() {quackBehavior.quack();}public void swim() {System.out.println("All ducks float, even decoys!");}public void setFlyBehavior(FlyBehavior fb) {flyBehavior = fb;}public void setQuackBehavior(QuackBehavior qb) {quackBehavior = qb;}}

FlyBehavior.java:

// FlyBehavio.javapublic interface FlyBehavior {public void fly();}

FlyWithWings.java:

// FlyWithWingspublic class FlyWithWings implements FlyBehavior {@Overridepublic void fly() {// TODO Auto-generated method stubSystem.out.println("I'am flying!");}}

FlyNoWay.java:

// FlyNoWay.javapublic class FlyNoWay implements FlyBehavior {@Overridepublic void fly() {// TODO Auto-generated method stubSystem.out.println("I can't fly!");}}

FlyRockedPowered.java:

// FlyRockedPoweredpublic class FlyRockedPowered implements FlyBehavior {@Overridepublic void fly() {// TODO Auto-generated method stubSystem.out.println("I' am flying with a rocked!");}}

QuackBehavior.java:

// QuackBehavior.javapublic interface QuackBehavior {public void quack();}

Quack.java

// Quack.javapublic class Quack implements QuackBehavior {    @Override    public void quack() {        // TODO Auto-generated method stub        System.out.println("Quack");    }}

MuteQuack.java

// QuackBehavior.javapublic class MuteQuack implements QuackBehavior {    @Override    public void quack() {        // TODO Auto-generated method stub        System.out.println("<< Silence >>");    }}

Squeak.java

// Squeak.javapublic class Squeak implements QuackBehavior {@Overridepublic void quack() {// TODO Auto-generated method stubSystem.out.println("Squeak");}}

MallardDuck.java:

// MallardDuckpublic class MallardDuck extends Duck {public MallardDuck() {quackBehavior = new Quack();flyBehavior = new FlyWithWings();}@Overridepublic void display() {// TODO Auto-generated method stubSystem.out.println("I'm a real Mallard duck");}}

ModelDuck.java:

// ModelDuckpublic class ModelDuck extends Duck {ModelDuck() {flyBehavior = new FlyNoWay();quackBehavior = new Quack();}@Overridepublic void display() {// TODO Auto-generated method stubSystem.out.println("I'm a model duck!");}}

Test.java

// Test.javapublic class Test {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubDuck mallard = new MallardDuck();mallard.performFly();mallard.performQuack();System.out.println("------------------- now, change the duck! --------------------");Duck model = new ModelDuck();model.performFly();System.out.println("------------------- now, set rocked on the model! --------------------");model.setFlyBehavior(new FlyRockedPowered());model.performFly();}}


原创粉丝点击