设计模式也是在工作中才会发现其作用。在规模较小的情况下,往往随意写来比较方便快速,可是对于大型的系统来说,各个部分用上合适的设计模式可以更好的维护系统,也更加的清晰。最近看了看一些web框架的源码,比如用的最多的Spring,一个web请求就会经过很多层的处理,其中用了很多设计模式,如果不了解则很难理解为什么要如此设计。所以还是从基础的开始吧。
下面说的是一个比较简单的 策略模式
。
策略模式的定义:一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
不像其他模式的定义显得很绕,策略模式的含义一看就比较清晰了。行为或者算法在运行时可以更改,首先能想到的便是通过面向对象中的多态来达到目的。在运行的过程中,根据需要动态的设定对象,对于调用者来说只要持有他们共同的接口就行了。正好,策略模式也正是这样。
看下面的例子(来自《Head First 设计模式》):
对于一只鸭子,它有飞和叫的行为,但是不同的鸭子表现出来的不一样。如果在一个类中表示所有的鸭子,则要进行各种判断,所以使用策略模式,将能够根据需要表现出不同鸭子的性质。
首先定义它的飞的行为:
1 2 3 4 5
| package io.lovs.learn.design.strategy;
public interface FlyBehavior { void fly(); }
|
再定义叫的行为:
1 2 3 4 5
| package io.lovs.learn.design.strategy;
public interface QuackBehavior { void quack(); }
|
对两种行为添加不同的实现,首先是飞的行为:
1 2 3 4 5 6 7 8
| package io.lovs.learn.design.strategy;
public class FlyWithWings implements FlyBehavior { @Override public void fly() { System.out.println("start fly"); } }
|
1 2 3 4 5 6 7 8
| package io.lovs.learn.design.strategy;
public class FlyNoWay implements FlyBehavior { @Override public void fly() { System.out.println("I can't fly"); } }
|
上面分别定义了一个飞和不回飞的行为
然后是叫的行为:
1 2 3 4 5 6 7 8
| package io.lovs.learn.design.strategy;
public class Squeak implements QuackBehavior { @Override public void quack() { System.out.println("Squeak"); } }
|
1 2 3 4 5 6 7 8
| package io.lovs.learn.design.strategy;
public class MuteQuack implements QuackBehavior { @Override public void quack() { System.out.println("silence"); } }
|
这里定义了叫和不叫的行为
然后定义一只抽象的鸭子,它将包含鸭子的基本属性,具体的鸭子可继承它然后实现各自的特点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package io.lovs.learn.design.strategy;
public abstract class Duck {
FlyBehavior flyBehavior; QuackBehavior quackBehavior;
public void display() { System.out.println("It's a duck"); }
abstract void fly(); abstract void quack();
public void setFlyBehavior(FlyBehavior flyBehavior) { this.flyBehavior = flyBehavior; }
public void setQuackBehavior(QuackBehavior quackBehavior) { this.quackBehavior = quackBehavior; } }
|
再来实现一只具体的鸭子
1 2 3 4 5 6 7 8 9 10 11 12 13
| package io.lovs.learn.design.strategy;
public class RealDuck extends Duck { @Override void fly() { flyBehavior.fly(); }
@Override void quack() { quackBehavior.quack(); } }
|
具体的某只鸭子继承了基本的鸭子的属性,在这里,主要实现了各自的叫和飞的行为。从抽象鸭子的定义中可以看到,它不直接实现飞和叫的功能,而是持有了飞和叫的接口,通过设置具体的飞与叫的类来实现该动作,达到了动态改变的效果,如果需要改变其行为,只要重新设置新的属性就好了。
测试类:
1 2 3 4 5 6 7 8 9 10 11 12
| package io.lovs.learn.design.strategy;
public class Test { public static void main(String[] args) { Duck duck = new RealDuck(); duck.setFlyBehavior(new FlyNoWay()); duck.setQuackBehavior(new Quack()); duck.display(); duck.fly(); duck.quack(); } }
|
输出:
1 2 3
| It's a duck I can't fly quack
|
策略模式相对简单,在书中也作为第一个讲解的内容。如果自己想象平时做的东西,在某些地方已经不经意中到了这样的模式。所以模式来源于实践当中,而单独看这些模式也没有意义,要在实际项目中真正的运用才算是发挥了真正的作用。这个模式就到这里吧。