策略模式.
策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”
abstract class Duck {
//声明接口
protected FlyBehavior flyBehavior;
protected QuackBehavior quackBehavior;
//调用接口中的方法
public void performFly(){
flyBehavior.fly();
}
//调用接口中的方法
public void performQuack(){
quackBehavior.quack();
}
//这是固定不会变化的方法.
public void swin(){
System.out.println("游泳");
}
//抽象方法子类实现.
public abstract void display();
//可以使其在运行时直接调用改变状态.
public FlyBehavior getFlyBehavior() {
return flyBehavior;
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public QuackBehavior getQuackBehavior() {
return quackBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
设定外观是野鸭
class MallardDuck extends Duck{
public MallardDuck(){
//通过无参构造方法直接定义野鸭的情况,野鸭用翅膀飞,嘎嘎叫.
//如果需要改变这个状态可以直接在运行时调用父类的set方法直接改变状态.
this.flyBehavior = new FlyWithWings();
this.quackBehavior = new Quack();
}
@Override
public void display() {
System.out.println("外观是野鸭");
}
}
设定红头鸭:
class RedheadDuck extends Duck{
//通过无参构造方法直接定义红头鸭的情况,背上绑个穿天猴飞,叫叫叫.
public RedheadDuck(){
this.flyBehavior = new FlyWithWings();
this.quackBehavior = new MuteQuack();
}
@Override
public void display() {
System.out.println("外观是红头鸭");
}
}
class RubberDuck extends Duck{
//和上面情况一样
public RubberDuck(){
this.flyBehavior = new FlyNoWay();
this.quackBehavior = new Squeak();
}
@Override
public void display() {
System.out.println("外观是橡皮鸭");
}
}
class DecoyDuck extends Duck{
//和上面情况一样
public DecoyDuck(){
this.flyBehavior = new FlyNoWay();
this.quackBehavior = new MuteQuack();
}
@Override
public void display() {
System.out.println("外观是幼儿鸭");
}
}
定义鸭子起飞的状态的接口类
public interface FlyBehavior {
void fly();
}
//以下类都是实现接口设定鸭子状态的类
class FlyWithWings implements FlyBehavior{
@Override
public void fly() {
System.out.println("用翅膀飞");
}
}
class FlyWithRocket implements FlyBehavior{
@Override
public void fly() {
System.out.println("背上绑个穿天猴飞");
}
}
class FlyWithKick implements FlyBehavior{
@Override
public void fly() {
System.out.println("被人一脚踢飞");
}
}
class FlyNoWay implements FlyBehavior{
@Override
public void fly() {
System.out.println("不会飞");
}
}
定义鸭子叫状态的接口
public interface QuackBehavior {
void quack();
}
//以下都是实现鸭子叫状态接口设定鸭子叫声的类.
class Quack implements QuackBehavior{
@Override
public void quack() {
System.out.println("嘎嘎叫");
}
}
class Squeak implements QuackBehavior{
@Override
public void quack() {
System.out.println("吱吱叫");
}
}
class MuteQuack implements QuackBehavior{
@Override
public void quack() {
System.out.println("叫叫叫");
}
}
策略模式,可以看到变化的抽离出来创建一个接口和实现接口的类,通过抽象类(不再是使用接口)来关联抽离出来的变化的属性方法.使用类来继承这个抽象类,根据自己的需求选择具体的策略,然后实现自己的需求,这样的适应性和代码的复用性就非常的好.如果需要重新添加一种属性方法状态,那么就可以直接实现这个接口,然后根据自己的需求添加方法,再自己的类中直接调用自己新添加的属性方法,就非常的方便.
策略模式的优点
(1)策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。
(2)使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。
策略模式的缺点
(1)客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道算法或行为的情况。
(2)由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。