时间:2017年08月31日星期四
说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com
教学源码:https://github.com/zccodere/s...
学习源码:https://github.com/zccodere/s...

第一章:策略模式简介

1-1 简介

课程大纲

什么是策略模式
策略模式如何实现
策略模式总结篇
实例案例分享

日常生活中的策略

World文档中的排版布局
购物支付过程中选择支付渠道

案例示意图

clipboard.png

策略模式定义

策略模式将可变的部分从程序中抽象分离成算法接口,
在该接口下分别封装一系列算法实现并使他们可以相互替换,
从而导致客户端程序独立于算法的改变。

第二章:策略模式应用

2-1 虚拟应用

模拟应用背景

通过代码来实现策略模式,通过开发与重构虚拟应用
使用策略模式实现,在不变更代码框架的前提下
不断的拥抱需求的变化,从而满足客户需求

项目背景:鸭子应用

clipboard.png

2-2 原有功能

代码编写

1.编写Duck类

package com.myimooc.designpattern.c7strategy;

/**
 * @title 策略模式
 * @describe 超类,所有的鸭子都要继承此类,抽象了鸭子的行为:显示和鸣叫
 * @author zc
 * @version 1.0 2017-08-31
 */
public abstract class Duck {
    
    /**
     * 鸭子发出叫声,通用行为,由超类实现
     */
    public void quack(){
        System.out.println("嘎嘎嘎");
    }
    
    /**
     * 显示鸭子的外观,鸭子的外观各不相同,声明为abstract,由子类实现
     */
    public abstract void display();
}

2.编写MallardDuck类

package com.myimooc.designpattern.c7strategy;

/**
 * @title 策略模式
 * @describe 绿脖子的鸭子
 * @author zc
 * @version 1.0 2017-08-31
 */
public class MallardDuck extends Duck {

    @Override
    public void display() {
        System.out.println("我的脖子是绿色的");
    }
}

3.编写RedheadDuck类

package com.myimooc.designpattern.c7strategy;

/**
 * @title 策略模式
 * @describe 红色头的鸭子
 * @author zc
 * @version 1.0 2017-08-31
 */
public class RedheadDuck extends Duck {

    @Override
    public void display() {
        System.out.println("我的头是红色的");
    }
}

2-3 增加功能

在原有功能的基础上新增飞行的功能

使用继承:父类统一实现
定义抽象方法:由子类自己实现
使用组合:复合优先于继承:多用组合,少用继承

继承优缺点

继承是重用代码的利器
但继承并不总是最好的工具

什么是组合

在类中增加一个私有域,引用另一个已有的类的实例,通过调用引用实例的方法从而获得新的功能,这种设计被称作组合(或复合)。

使用组合增加飞行功能

实现:将飞行行为抽象为接口,在父类中持有该接口,并由该接口代理飞行行为
优点:足够灵活;复用代码,更易于维护
缺点:策略类会增多;所有策略类都需要对外暴露

2-4 实现功能

代码编写

1.编写FlyingStrategy类

package com.myimooc.designpattern.c7strategy;

/**
 * @title 策略模式
 * @describe 策略接口,实现鸭子的飞行行为
 * @author zc
 * @version 1.0 2017-08-31
 */
public interface FlyingStrategy {
    
    /**
     * 飞行行为的方法
     */
    void performFly();
    
}

2.编写FlyWithWin类

package com.myimooc.designpattern.c7strategy.impl;

import com.myimooc.designpattern.c7strategy.FlyingStrategy;

/**
 * @title 策略模式
 * @describe 实现鸭子的飞行行为,用翅膀飞行的类
 * @author zc
 * @version 1.0 2017-08-31
 */
public class FlyWithWin implements FlyingStrategy{

    @Override
    public void performFly() {
        System.out.println("振翅高飞");
    }
}

3.修改Duck类

package com.myimooc.designpattern.c7strategy;

/**
 * @title 策略模式
 * @describe 超类,所有的鸭子都要继承此类,抽象了鸭子的行为:显示和鸣叫
 * @author zc
 * @version 1.0 2017-08-31
 */
public abstract class Duck {
    
    /**
     * 鸭子发出叫声,通用行为,由超类实现
     */
    public void quack(){
        System.out.println("嘎嘎嘎");
    }
    
    /**
     * 显示鸭子的外观,鸭子的外观各不相同,声明为abstract,由子类实现
     */
    public abstract void display();
    
    // 组合进飞行的策略接口
    private FlyingStrategy flyingStrategy;

    public void setFlyingStrategy(FlyingStrategy flyingStrategy) {
        this.flyingStrategy = flyingStrategy;
    }
    
    /**
     * 鸭子的飞行功能
     */
    public void fly(){
        // 由飞行策略接口执行飞行的动作
        flyingStrategy.performFly();
    }
}

4.修改MallardDuck类

package com.myimooc.designpattern.c7strategy;

import com.myimooc.designpattern.c7strategy.impl.FlyWithWin;

/**
 * @title 策略模式
 * @describe 绿脖子的鸭子
 * @author zc
 * @version 1.0 2017-08-31
 */
public class MallardDuck extends Duck {
    
    public MallardDuck() {
        super();
        super.setFlyingStrategy(new FlyWithWin());
    }
    
    @Override
    public void display() {
        System.out.println("我的脖子是绿色的");
    }
}

5.修改RedheadDuck类

package com.myimooc.designpattern.c7strategy;

import com.myimooc.designpattern.c7strategy.impl.FlyWithWin;

/**
 * @title 策略模式
 * @describe 红色头的鸭子
 * @author zc
 * @version 1.0 2017-08-31
 */
public class RedheadDuck extends Duck {

    public RedheadDuck() {
        super();
        super.setFlyingStrategy(new FlyWithWin());
    }
    
    @Override
    public void display() {
        System.out.println("我的头是红色的");
    }
}

6.编写DuckTest类

package com.myimooc.designpattern.c7strategy;

/**
 * @title 策略模式
 * @describe 测试类
 * @author zc
 * @version 1.0 2017-08-31
 */
public class DuckTest {
    
    public static void main(String[] args) {
        System.out.println("测试鸭子程序");
        System.out.println("*************************");
        
        Duck duck = null;
//        duck = new MallardDuck();
//        duck = new RedheadDuck();
//        duck = new RubberDuck();
//        duck = new BigYellowDuck();
        duck = new SpaceDuck();
        
        duck.display();
        duck.quack();
        duck.fly();
        
        System.out.println("*************************");
        System.out.println("测试程序完毕");
    }
    
}

2-5 复用代码

业务场景

需要增加橡胶鸭、大黄鸭,它们都有一个共同的特点,不会飞行。
不会飞行也是一种飞行行为,所以可以通过良好的抽象复用代码。

代码编写

1.编写FlyNoWay类

package com.myimooc.designpattern.c7strategy.impl;

import com.myimooc.designpattern.c7strategy.FlyingStrategy;

/**
 * @title 策略模式
 * @describe 实现鸭子的飞行行为,不会飞行的策略类
 * @author zc
 * @version 1.0 2017-08-31
 */
public class FlyNoWay implements FlyingStrategy {

    @Override
    public void performFly() {
        System.out.println("我不会飞行!");
    }

}

2.编写RubberDuck类

package com.myimooc.designpattern.c7strategy;

import com.myimooc.designpattern.c7strategy.impl.FlyNoWay;

/**
 * @title 策略模式
 * @describe 橡胶鸭
 * @author zc
 * @version 1.0 2017-08-31
 */
public class RubberDuck extends Duck{
    
    public RubberDuck() {
        super();
        super.setFlyingStrategy(new FlyNoWay());
    }
    
    @Override
    public void display() {
        System.out.println("我全身发黄,嘴巴很红");
    }

    @Override
    public void quack() {
        System.out.println("嘎~嘎~嘎~");
    }
}

3.编写BigYellowDuck类

package com.myimooc.designpattern.c7strategy;

import com.myimooc.designpattern.c7strategy.impl.FlyNoWay;

/**
 * @title 策略模式
 * @describe 大黄鸭
 * @author zc
 * @version 1.0 2017-08-31
 */
public class BigYellowDuck extends Duck{
    
    public BigYellowDuck() {
        super();
        super.setFlyingStrategy(new FlyNoWay());
    }
    
    @Override
    public void display() {
        System.out.println("我身体很大,全身黄黄");
    }
}

4.修改DuckTest类

package com.myimooc.designpattern.c7strategy;

/**
 * @title 策略模式
 * @describe 测试类
 * @author zc
 * @version 1.0 2017-08-31
 */
public class DuckTest {
    
    public static void main(String[] args) {
        System.out.println("测试鸭子程序");
        System.out.println("*************************");
        
        Duck duck = null;
//        duck = new MallardDuck();
//        duck = new RedheadDuck();
//        duck = new RubberDuck();
//        duck = new BigYellowDuck();
        duck = new SpaceDuck();
        
        duck.display();
        duck.quack();
        duck.fly();
        
        System.out.println("*************************");
        System.out.println("测试程序完毕");
    }
    
}

2-6 新增种类

业务场景

现在又需增加太空鸭,太空鸭不能自己飞行,需要借助先进的科学技术。

1编写FlyWithRocket类

package com.myimooc.designpattern.c7strategy.impl;

import com.myimooc.designpattern.c7strategy.FlyingStrategy;

/**
 * @title 策略模式
 * @describe 实现鸭子的飞行行为,使用火箭飞行策略类
 * @author zc
 * @version 1.0 2017-08-31
 */
public class FlyWithRocket implements FlyingStrategy {

    @Override
    public void performFly() {
        System.out.println("用火箭在太空遨游");
    }
}

2.编写SpaceDuck类

package com.myimooc.designpattern.c7strategy;

import com.myimooc.designpattern.c7strategy.impl.FlyWithRocket;

/**
 * @title 策略模式
 * @describe 太空鸭
 * @author zc
 * @version 1.0 2017-08-31
 */
public class SpaceDuck extends Duck {

    public SpaceDuck() {
        super();
        super.setFlyingStrategy(new FlyWithRocket());
    }
    
    @Override
    public void display() {
        System.out.println("我头戴宇航盔");
    }
    
    @Override
    public void quack() {
        System.out.println("我通过无线电与你通信");
    }

}

3.修改DuckTest类

package com.myimooc.designpattern.c7strategy;

/**
 * @title 策略模式
 * @describe 测试类
 * @author zc
 * @version 1.0 2017-08-31
 */
public class DuckTest {
    
    public static void main(String[] args) {
        System.out.println("测试鸭子程序");
        System.out.println("*************************");
        
        Duck duck = null;
//        duck = new MallardDuck();
//        duck = new RedheadDuck();
//        duck = new RubberDuck();
//        duck = new BigYellowDuck();
        duck = new SpaceDuck();
        
        duck.display();
        duck.quack();
        duck.fly();
        
        System.out.println("*************************");
        System.out.println("测试程序完毕");
    }
    
}

第三章:策略模式总结

3-1 总结

策略模式中的设计原则

找出应用中需要变化的部分,把他们独立出来,不要和那些不需要变化的代码混在一起
面向接口编程,而不是面向实现编程
多用组合,少用继承

策略模式的实现

通过分离变化得出的策略接口Strategy
Strategy接口的实现类
客户程序中有一个Strategy
在客户程序中选择和组装正确的Strategy实现类

策略模式的优点

使用了组合,使架构更加灵活
富有弹性,可以较好的应对变化(开闭原则)
更好的代码复用性(相对于继承)
消除大量的条件语句

策略模式的缺点

客户代码需要了解每个策略实现的细节
增加了对象的数目
所有策略类都需要对外暴露

策略模式的适用场景

许多相关的类仅仅是行为差异
运行时选取不同的算法变体
通过条件语句在多个分支中选取其中一个

妙手空空
1.3k 声望370 粉丝

博观而约取,厚积而薄发