java设计模式---策略模式

来源:互联网 发布:住院电子病历软件 编辑:程序博客网 时间:2024/06/13 13:34


所谓策略模式可以简单的想成:创建一个能够根据所传递的参数对象的不同而具有不同行为的方法。

当然,当你需要装成高大上的样子的话,你可以这样跟你的朋友、上司说:策略模式定义了算法,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。


栗子说话:

   我们有一个鸭子应用,有各种鸭子,可以游泳,可以叫

当然我们有设计了一个超类,并让各种鸭子都继承自这个超类,然后我们所有的鸭子都具有了 呱呱叫的功能了,如下图:

看上去是可以的,而且很多时候我们都是这样设计的,但是这个时候 有加上了一个 fly()  也就是飞的行为,这有什么困难,超类加上 就ok啦

事情来了,然而并不是所有的鸭子都会飞的,如此继承,那不会飞的鸭子也会飞了,再继续想,有的鸭子咕咕叫,有的呱呱叫,还有的不叫,怎么办,那这样设计就太坑啦



所以我们了解了:使用继承并不能很好的解决这种问题,因为鸭子的行为在子类里不断的改变,并且让所有的子类都有这些行为是不恰当的,你可能会想到用接口,然而java接口不具有实现代码,所有继承接口无法达到代码复用

这就意味着:无论何时需要修改某个行为,你必须得往下追踪并在每一个定义此行为的类中去修改它,而且还容易出错


刚好就有这样一个规则设计用于此情况:找出应用中可能需要变化之处,把他们独立出来,不要和没变化的代码混在一起,也就是把变化的行为提取出来,方便以后可以轻易的扩充和修改而不影响不需要改变的部分。


在此,我们又两个接口,FlyBehavior 和 QuackBehavior 还有他们对应的实现类


把飞行和叫的行为委托给其他人来处理,而不是定义在超类或者是子类里面

定义超类:Duck.java

public abstract class Duck {

public FlyBehavior flyBehavior;
public QuackBehavior quackBehavior;

public Duck() {}

public abstract void display();
public void swim() {
System.out.println("I can swimming");
}

public void performFly() {
flyBehavior.fly();//委托给行为类
}


public void performQuack() {
quackBehavior.quack();//委托给行为类
}

}


俩接口:

//所有飞行行为实现

public interface FlyBehavior {
public void fly();//fly

}

//所有叫行为实现

public interface QuackBehavior {
public void quack();
}


然后就是我们具体的实现类了,我们的实现类可以有多个,什么会飞的啊  不会飞的啊,还有呱呱叫的,不会叫的,根据具体行为来实现


将飞行和叫的行为和超类剥离开,让行为对象去叫,去飞,我们只关心该对象如何叫就行


//不会飞

public class FlyNoWay implements FlyBehavior{


@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("I can't fly");
}
}

//会飞

public class FlyWithWings implements FlyBehavior{


@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("I can fly");
}

}

//呱呱叫的

public class Quack implements QuackBehavior{


@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("I can Quack");

}

}


//然后来看下我们的具体的鸭MallardDuck

public class MallardDuck extends Duck {


@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("I am MallardDuck");
}

public MallardDuck() {
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}

}



//测试

public class MiniDuckSimulator {

public static void main(String[] args) {
Duck mallardDuck = new MallardDuck();
mallardDuck.display();
mallardDuck.performFly();
mallardDuck.performQuack();
mallardDuck.swim();
}

}

//output:

I am MallardDuck
I can fly
I can Quack
I can swimming



接下来我们看下如何动态的去改变这些行为


在Duck类中新加方法:


public abstract class Duck {


public FlyBehavior flyBehavior;
public QuackBehavior quackBehavior;


public Duck() {
}


public abstract void display();


public void swim() {
System.out.println("I can swimming");
}


public void performFly() {
flyBehavior.fly();// 委托给行为类
}


public void performQuack() {
quackBehavior.quack();// 委托给行为类
}


public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}


public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}

}


修改我们的测试类MiniDuckSimulator


public class MiniDuckSimulator {


public static void main(String[] args) {
Duck mallardDuck = new MallardDuck();
mallardDuck.display();
mallardDuck.performFly();
mallardDuck.performQuack();
mallardDuck.swim();

System.out.println("==========================");

Duck modelDuck = new ModelDuck();
modelDuck.performFly();
modelDuck.performQuack();
modelDuck.setFlyBehavior(new FlyWithWings());
modelDuck.performFly();
}

}

output:

I am MallardDuck
I can fly
I can Quack
I can swimming
==========================
I can't fly
I can Quack
I can fly



改变前:第一次调用performFly()会被委托给flyBehavior对象,setter方法会将会飞的行为设置鸭中,然后鸭就具有了飞行的行为

可以看到,我们鸭子的行为被动态的改变了

在运行时想改变鸭子的行为,只需要调用鸭子的setter方法就


到此

搞定!




0 0