title: Day60-设计模式-策略模式
date: 2021-03-29 19:38:42
author: Liu_zimo
设计模式
- 设计模式分为三种类型,共23种
- 创建型模式:单例模式、抽象工厂模式、原型模式、建造者模式、工厂模式。
- 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
- 行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)。
策略模式
- 鸭子问题
- 有各种鸭子(比如野鸭、北京鸭、水鸭等,鸭子有各种行为,比如叫、飞行等)
- 显示鸭子的信息
- 传统方案:
- 其它鸭子,都继承了Duck类,所以fly让所有子类都会飞了,这是不正确的
- 上面说的1的问题,其实是继承带来的问题:对类的局部改动,尤其超类的局部改动,会影响其他部分。会有溢出效应
- 为了改进1问题,我们可以通过覆盖fly方法来解决 => 覆盖解决
- 问题又来了,如果我们有一个玩具鸭子ToyDuck,这样就需要ToyDuck去覆盖Duck的所有实现的方法 => 解决思路策略模式
package com.zimo.设计模式.行为型模式.策略模式.传统方式;
/**
* 设计模式 - 策略模式:鸭子问题 - 传统方案
* 鸭子抽象父类
* @author Liu_zimo
* @version v0.1 by 2021/3/29 19:49
*/
public abstract class Duck {
public Duck() { }
public abstract void display();
public void quack(){ System.out.println("ga ga ga"); }
public void swim(){ System.out.println("swimming....."); }
public void fly(){ System.out.println("fly..."); }
}
-----------------------------------------------------------------
package com.zimo.设计模式.行为型模式.策略模式.传统方式;
/**
* 设计模式 - 策略模式:鸭子问题 - 传统方案
* 北京鸭
* @author Liu_zimo
* @version v0.1 by 2021/3/29 19:54
*/
public class PekingDuck extends Duck{
@Override
public void display() { System.out.println("北京鸭"); }
@Override
public void fly() { System.out.println("not fly"); }
}
-----------------------------------------------------------------
package com.zimo.设计模式.行为型模式.策略模式.传统方式;
/**
* 设计模式 - 策略模式:鸭子问题 - 传统方案
* 野鸭
* @author Liu_zimo
* @version v0.1 by 2021/3/29 19:53
*/
public class WildDuck extends Duck{
@Override
public void display() { System.out.println("野鸭.."); }
}
-----------------------------------------------------------------
package com.zimo.设计模式.行为型模式.策略模式.传统方式;
/**
* 设计模式 - 策略模式:鸭子问题 - 传统方案
* 玩具鸭
* @author Liu_zimo
* @version v0.1 by 2021/3/29 19:56
*/
public class ToyDuck extends Duck{
@Override
public void display() { System.out.println("玩具鸭"); }
@Override
public void quack() { }
@Override
public void swim() { }
@Override
public void fly() { }
}
基本介绍
- 策略模式(Strategy Pattern)中,定义算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
- 这算法体现了几个设计原则
- 第一、把变化的代码从不变的代码中分离出来
- 第二、针对接口编程而不是具体类(定义了策略接口)
- 第三、多用组合/聚合,少用继承(客户通过组合方式使用策略)。
- 说明:客户context有成员变量strategy或者其他的策略接口,至于需要使用到哪个策略,我们可以在构造器中指定
- 思路分析:
- 策略模式:分别封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象。
- 原则就是:分离变化部分,封装接口,基于接口编程各种功能。
- 此模式让行为的变化独立于算法的使用者
package com.zimo.设计模式.行为型模式.策略模式.改进版;
/**
* 设计模式 - 策略模式:鸭子问题
* 飞行行为接口
* @author Liu_zimo
* @version v0.1 by 2021/3/29 20:38
*/
public interface FlyBehavior {
void fly();
}
-----------------------------------------------------------------
package com.zimo.设计模式.行为型模式.策略模式.改进版;
/**
* 设计模式 - 策略模式:鸭子问题
* 擅长飞行
* @author Liu_zimo
* @version v0.1 by 2021/3/29 20:39
*/
public class GoodFly implements FlyBehavior{
@Override
public void fly() { System.out.println("擅长飞行"); }
}
-----------------------------------------------------------------
package com.zimo.设计模式.行为型模式.策略模式.改进版;
/**
* 设计模式 - 策略模式:鸭子问题
* 普通飞行
* @author Liu_zimo
* @version v0.1 by 2021/3/29 20:39
*/
public class BadFlyBehavior implements FlyBehavior{
@Override
public void fly() { System.out.println("普通飞行"); }
}
-----------------------------------------------------------------
package com.zimo.设计模式.行为型模式.策略模式.改进版;
/**
* 设计模式 - 策略模式:鸭子问题
* 不会飞行
* @author Liu_zimo
* @version v0.1 by 2021/3/29 20:41
*/
public class NotFlyBehavior implements FlyBehavior{
@Override
public void fly() { System.out.println("不会飞行"); }
}
-----------------------------------------------------------------
package com.zimo.设计模式.行为型模式.策略模式.改进版;
/**
* 设计模式 - 策略模式:鸭子问题
* 鸭子抽象类
* @author Liu_zimo
* @version v0.1 by 2021/3/29 20:42
*/
public abstract class Duck {
FlyBehavior flyBehavior; // 飞行属性
public Duck() { }
public abstract void display();
public void fly(){
if (flyBehavior != null){ // 改进
flyBehavior.fly();
}
}
}
-----------------------------------------------------------------
package com.zimo.设计模式.行为型模式.策略模式.改进版;
/**
* 设计模式 - 策略模式:鸭子问题
* 野鸭
* @author Liu_zimo
* @version v0.1 by 2021/3/29 20:45
*/
public class WildDuck extends Duck {
public WildDuck() { flyBehavior = new GoodFly(); }
@Override
public void display() { System.out.println("野鸭"); }
}
-----------------------------------------------------------------
package com.zimo.设计模式.行为型模式.策略模式.改进版;
/**
* 设计模式 - 策略模式:鸭子问题
* 北京鸭
* @author Liu_zimo
* @version v0.1 by 2021/3/29 20:47
*/
public class PekingDuck extends Duck{
public PekingDuck() { flyBehavior = new BadFlyBehavior(); }
@Override
public void display() { System.out.println("北京鸭"); }
}
-----------------------------------------------------------------
package com.zimo.设计模式.行为型模式.策略模式.改进版;
/**
* 设计模式 - 策略模式:鸭子问题
* 野鸭
* @author Liu_zimo
* @version v0.1 by 2021/3/29 20:52
*/
public class ToyDuck extends Duck{
public ToyDuck() { flyBehavior = new NotFlyBehavior(); }
@Override
public void display() { System.out.println("玩具鸭"); }
}
-----------------------------------------------------------------
package com.zimo.设计模式.行为型模式.策略模式.改进版;
/**
* @author Liu_zimo
* @version v0.1 by 2021/3/29 20:54
*/
public class Client {
public static void main(String[] args) {
WildDuck wildDuck = new WildDuck();
wildDuck.fly();
ToyDuck toyDuck = new ToyDuck();
toyDuck.fly();
PekingDuck pekingDuck = new PekingDuck();
pekingDuck.fly();
}
}
JDK - Arrays应用分析
- JDK的Arrays的Comparator就使用了策略模式
- Comparator为策略接口
- Arrays.sort(data, Comparator);
注意事项和细节
- 策略模式的关键是:分析项目中变化部分与不变部分
- 策略模式的核心思想是:多用组合/聚合少用继承;用行为类组合,而不是行为的继承。更有弹性
- 体现了“对修改关闭,对扩展开放”原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为)即可,避免了使用多重转移语句( if…else if…else)
- 提供了可以替换继承关系的办法:策略模式将算法封装在独立的Strategy类中使得你可以独立于其Context改变它,使它易于切换、易于理解、易于扩展
- 需要注意的是:每添加一个策略就要增加一个类,当策略过多是会导致类数目庞大