设计模式之策略模式

策略模式

什么是策略

一般是指:

  1. 可以实现目标的方案集合。
  2. 根据形势发展而制定的行动方针和斗争方法。
  3. 有斗争艺术,能注意方式方法。

“策略”就是为了实现某一个目标,首先预先根据可能出现的问题制定的若干对应的方案,并且,在实现目标的过程中,根据形势的发展和变化来制定出新的方案,或者根据形势的发展和变化来选择相应的方案,最终实现目标。

(引用百度百科)

什么是策略模式

策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法。

策略模式:

  • 定义了一族算法(业务规则);
  • 封装了每个算法;
  • 这族的算法可互换代替(interchangeable)。

策略模式UML图

(引用维基百科)

类图

stragy_pattren_uml.png

  • Client

    发起算法调用

  • Context(客户端)

    持有具体策略实现的引用,调用策略接口API,进行方法调用。

    可以持有全部策略引用,根据不同的策略标识获取已初始化的策略类,进而执行对应的策略行为。也可以通过构造方法传入策略类。

  • Strategy(策略接口)

    决定实现策略所必需的接口。

  • AddStrategy(具体策略实现者)

    实现策略接口,具体策略有不同的实现方式。达到解耦的目的。

实现

注。以下实现参考 <Head First 设计模式>

strategy_pattern_h1.png

1. 定义策略接口

/**
 * 剥离出来的特定的飞行行为
 */
public interface FlyBehavior {
    void fly();
}


/**
 * 剥离出来的特定的呼叫行为
 */
public interface QuackBehavior {
    void quack();
}

2. 定义策略实现类

public class Quack implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("定义会呱呱叫的鸭子行为!!!");
    }
}

public class FlyWithWings implements FlyBehavior{
    @Override
    public void fly() {
        System.out.println("定义会飞的鸭子行为!!!");
    }
}

3. 定义Duck超类

/**
 * 鸭子超类
 * 需求一: 需要会飞的鸭子。
 *      会飞这个动作并不是所有鸭子都具备的行为。如果在超类上加上新的行为,将会使得某些子类具有这个不恰当的行为。
 *   方式一: 定义新的接口。让需要的这种鸭子行为的类实现它。但这不是一个好的办法。每当新增一个鸭子的种类,都要去实现这个接口。×
 *   如果每次新的需求一来,都会变化到某方面的代码,那么你可以确定,这部分的代码需要被抽取出来。
 *   方式二: 为要要区分开 变化和不变化的部分。准备再组类。一是fly相关,一是quack相关
 *   当我们创建特定对象的时候,指定特定的类型的飞行行为给它。我们需要在鸭子超类中包含设定行为了方法。就可以在运行时动态地改变子类的飞行行为
 */
public abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    /**
     * 外观不同,定义抽象方法让子类实现
     */
    public abstract void display();

    /**
     * 呱呱叫
     */
    public void quack() {
        System.out.println("所有鸭子都会: 呱呱叫!!!");
    }
    /**
     * 游泳
     */
    public void swim() {
        System.out.println("所有鸭子都会: 游泳!!!");
    }

    public void performFly() {
        flyBehavior.fly();
    }

    public void performQuack() {
        quackBehavior.quack();
    }

}

4. 定义Duck实现类

/**
 * 绿头鸭子
 */
public class MallardDuck extends Duck{
    public MallardDuck() {
        quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();
    }
    public void display() {
        System.out.printf("mallard duck.");
    }
}

/**
* 闲鱼鸭
*/
public class NothingDuck extends Duck {
    @Override
    public void display() {
        System.out.println("Nothing duck");
    }
}

5. Main

/**
 * 不再把鸭子的行为说成「一组行为」,我们开始把行为想成是「一族算法」
 * 鸭子的行为不是继承而来,而是和适当的行为对象组合而来。
 * 设计原则: 多用组合,少用继承。
 */
public class T {
    public static void main(String[] args) {
        MallardDuck mallardDuck = new MallardDuck();
        mallardDuck.performFly();
        mallardDuck.performQuack();

        System.out.println("--------Nothing Duck--------------");
        NothingDuck nothingDuck = new NothingDuck();
        nothingDuck.performFly();
    }
}

总结

  1. 针对接口编程,而不是针对实现编程
  2. 无论何时你需要修改某个行为,你必须得往下追踪并修改每一个定义此行为的类,一不小心,可能造成新的错误。换句话说,如果每次新的需求一来,都会变化到某方面的代码,那么你就可以确定,这部分的代码需要被抽出来,和其他闻风不动的代码有所区隔。
  3. 把会变化的部分取出并封装起来,以便以后可以轻易地扩充此部分,而不影响不需要变化的其他部分。
  4. 针对接口编程,关键就在多态。利用多态,程序可以针对超类编程,执行时会根据实际状况执行到真正的行为,不会被绑死在超类的行为上。
  5. 策略模式提供了对"开闭原则"完美支持,用户可以在不修改原有系统的基础上选择算法行为,也可以灵活的增加新的算法行为。
  6. 策略模式提供了可替换继承关系的办法。继承使得动态改变算法或行为变得不可能。但是使用策略模式可以实现解耦。
  7. 策略模式缺点是使用者必须知道所有策略类,并自行决定使用哪一个策略类。也就意味着使用者必须理解这些算法之间的区别,以便在恰当的时机选择恰当的算法类。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值