第1章 引子:什么是策略模式
1-1 策略模式简介
- 什么是策略模式
- 策略模式如何实现
- 策略模式总结篇
- 实际案例分享
日常生活中的例子:
- 文本编辑软件–》布局 –》布局算法
- 算法实现1
- 算法实现2
- 算法实现3
- 购物–》支付–》支付算法
- 招商银行
- 建设银行
- XXX银行
共同点:
- 抽象出不变部分
- 定义算法族分别封装起来
- 客户端不会受算法改变的影响
- 对新增需求弹性的支持
策略模式将可变的部分从程序中抽象分离成算法接口,在改接口下分别
封装一系列算法实现并使他们可以相互替换,从而导致客户端程序独立
独立于算法的改变。
第2章 光荣与梦想——鸭子应用:策略模式的实现
2-1 光荣与梦想:模拟应用背景介绍
光荣与梦想:鸭子应用
- 飞行的能力
- 更多类型的鸭子
每六个月发布一款产品
鸭子的鸣叫
- 鸭子的显示
- 原有的功能
- 飞行的能力
2-2 求索之路:鸭子如何才能飞
原有代码
/*
* 超类,所有的鸭子都要继承此类
* 抽象了鸭子的行为:显示和鸣叫
*/
public abstract class Duck {
/*
* 鸭子发出叫声
* 通用行为,由超类实现
*/
public void quack(){
System.out.println("嘎嘎嘎");
}
/*
* 显示鸭子的外观
* 鸭子的外观各不相同,声明为abstract, 由子类实现
*/
public abstract void display();
}
public class MallardDuck extends Duck {
public MallardDuck(){
super();
}
@Override
public void display() {
System.out.println("我的脖子是绿色的");
}
}
public class RedheadDuck extends Duck {
public RedheadDuck(){
super();
}
@Override
public void display() {
System.out.println("我的头是红色的");
}
}
让我们的鸭子飞起来
方案一:
在父类中提供实现方法,子类通过继承获得父类中的飞行行为
public void fly(){
System.out.println("用翅膀飞行");
}
- 优点
- 简(cu)单(bao)易(chou)用(lou),已有应用可以快速添加飞行的能力
- 缺点
- 不具有灵活性,对未来变更支持差。
- 需要通过在子类中覆写飞行的方法以提供新的飞行行为。这很容易造成错误(粗心的程序员忘记覆写)。
方案二:抽象方法
在父类中提供抽象方法,强迫子类实现自己的飞行行为
public abstract void fly();
- 优点
- 足够灵活。
- 小伙伴再也不会忘记覆写代码了。
- 缺点
- 累死小伙伴了。
- 每个子类都要实现一遍代码,及时是相同的行为也不例外。
- 代码重复,没有复用代码。
2-3 柳暗花明:策略让鸭子飞上天
集成是重用代码的利器
但继承并不总是最好的工具
Favor composition over inheritace ———— Effective Java
复合优先与继承
多用组合,少用继承
面向对象 组合
Car has-a Tyre
汽车通过使用轮胎获得轮胎的能力
在类中增加一个私有域,引用另一个已有的类的实例,通过调
用引用实例的方法从而获得新的功能,这种设计被称作组合(复合)。
方案三:组合
将飞行行为抽象为接口,在父类中持有该接口,并由该接口代理飞行行为。
public interface FlyingStragety{
void performFly();
}
private FlyingStragety flyingStragety;
public void fly(){
flyingStragety.performFly();
}
- 优点
- 足够灵活。
- 复用代码,更易于维护。
- 缺点
- 见第三章总结中缺点
2-4 脚踏实地:用代码放飞鸭子
/*
* 策略接口,实现鸭子的飞行行为
*/
public interface FlyingStragety {
void performFly();
}
/*
* 超类,所有的鸭子都要继承此类
* 抽象了鸭子的行为:显示和鸣叫
*/
public abstract class Duck {
/*
* 鸭子发出叫声
* 通用行为,由超类实现
*/
public void quack(){
System.out.println("嘎嘎嘎");
}
/*
* 显示鸭子的外观
* 鸭子的外观各不相同,声明为abstract, 由子类实现
*/
public abstract void display();
private FlyingStragety flyingStragety;
public void setFlyingStragety(FlyingStragety flyingStragety) {
this.flyingStragety = flyingStragety;
}
public void fly(){
flyingStragety.performFly();
}
}
public class FlyWithWin implements FlyingStragety {
public void performFly() {
System.out.println("振翅高飞");
}
}
public class MallardDuck extends Duck {
public MallardDuck(){
super();
super.setFlyingStragety(new FlyWithWin());
}
@Override
public void display() {
System.out.println("我的脖子是绿色的");
}
}
public class RedheadDuck extends Duck {
public RedheadDuck(){
super();
super.setFlyingStragety(new FlyWithWin());
}
@Override
public void display() {
System.out.println("我的头是红色的");
}
}
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.display();
duck.quack();
duck.fly();
System.out.println("************************");
System.out.println("测试完毕");
}
}
2-5 拥抱变化:用策略模式提供高复用性代码
新加两款产品,不能飞行
public class FlyNoWay implements FlyingStragety {
public void performFly() {
System.out.println("我不会飞行!");
}
}
public class RubberDuck extends Duck {
public RubberDuck() {
super();
super.setFlyingStragety(new FlyNoWay());
}
@Override
public void display() {
System.out.println("我全身发黄,嘴巴很红");
}
public void quack(){
System.out.println("嘎~嘎~嘎~");
}
}
public class BigYellow extends Duck {
public BigYellow() {
super();
super.setFlyingStragety(new FlyNoWay());
}
@Override
public void display() {
System.out.println("我身体很大,全身黄黄");
}
}
2-6 万变不离其宗:向宇宙进军
新增太空鸭
public class FlyWithRocket implements FlyingStragety {
public void performFly() {
System.out.println("用火箭在太空遨游");
}
}
public class SpaceDuck extends Duck {
public SpaceDuck() {
super();
super.setFlyingStragety(new FlyWithRocket());
}
@Override
public void display() {
System.out.println("我头戴宇航头盔");
}
public void quack(){
System.out.println("我通过无线电与你通信");
}
}
橡胶鸭、大黄鸭
- 代码复用
太空鸭
- 更换策略模式
一生二,二生三,三生无穷!
第3章 总结篇
3-1 知识点总结
策略模式中的设计原则
- 找出应用中需要变化的部分,把他们独立出来,不要和那些不需要变化的代码混在一起。
- 面向接口编程,而不是面向实现编程。
- 多用组合,少用继承。
策略模式的实现
- 通过分离变化得出的策略接口Strategy
- Strategy的实现类
- 客户程序“有一个”Strategy
- 在客户程序中选择/组装正确的Strategy实现
策略模式的优点
- 使用了组合,使架构更加灵活
- 富有弹性,可以较好的应对变化(开—闭原则)
- 更好的代码复用性(相对于继承)
- 消除大量的条件语句
策略模式的缺点
- 客户代码需要了解每个策略实现的细节
- 增加了对象的数目
策略模式的适用场景
- 许多相关的类仅仅是行为差异
- 运行时选取不同的算法变体
- 通过条件语句在多个分支中选取一