设计模式(25)行为型模式 - 策略模式

前言

温故而知新

还是先复习学习到的行为型模式:

  • 模板方法模式:定义一个算法骨架,特定的步骤延迟到子类实现(请客流程:点单-》吃-》买单,吃什么由子类负责)
  • 命令模式:将命令封装成对象,聚合执行者,命令请求者仅需调用命令对象即可完成命令(遥控器按钮就是命令对象,按下按钮即可完成开关灯)
  • 访问者模式:将施加于对象结构的元素上的操作隔离,封装成具体访问者,修改访问者并不会改动对象结构(购物车是一个对象结构,内部存放需要商品元素,顾客可以查看商品质量,收银员可以查看商品价格)
  • 迭代器模式:将聚合对象的存储功能和遍历功能分隔,遍历功能封装成迭代器,聚合对象工厂方法创建对应的迭代器(迭代器遍历Linux目录)
  • 观察者模式:定义对象间的一对多的依赖关系,当对象改变时,自动通知所有依赖的对象并自动更新对象数据(气象局天气数据改变,对应的APP的天气数据也会改变)
  • 中介者模式:定义一个中介者封装对象间的交互关系,使对象间无显示的交互,可以通过中介对象访问任一其他对象(QQ聊天不需要知道对方的IP,通过服务器可以相互通信)
  • 备忘录模式:定义一个备忘录角色,用于存储对象的内部状态,提供给对象恢复状态的功能(游戏的存档读档)
  • 解释器模式:给分析对象定义一个语言,并定义该语言的文法表示,设计一个解释器解释语言中的句子(加减法解释器可以解释表达式字符串)
  • 状态模式:允许对象在其内部状态改变时改变它的行为(进程的五个状态,每个状态都有自己的方法,能够切换到其他状态)

行为型模式有11种,接下来学习第10种设计模式:策略模式


现实中的问题

其实在现实生活中,可以感受到,当我们为了实现一个目标,会有多种策略可以选择
如,出行时可以选择走路、骑自行车、乘公交车。。。
存储对象,可以选择不同的数据结构:数组、List、Map、Set等等
在这里插入图片描述
这一种种选择,可以称为策略,我们可以根据环境或者条件的不同选择不同的策略来完成该项任务


策略模式

什么是策略模式?

策略模式(Strategy Pattern):定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。策略模式是一种对象行为型模式

为什么要策略模式?

在软件系统中,有许多算法可以实现某一功能,如查找、排序等,一种常用的方法是硬编码(Hard Coding)在一个类中,如需要提供多种查找算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法

当然也可以将这些查找算法封装在一个统一的方法中,通过if…else…等条件判断语句来进行选择。

这两种实现方法我们都可以称之为硬编码(Hard Coding),如果需要增加一种新的查找算法,需要修改封装算法类的源代码;更换查找算法,也需要修改客户端调用代码。在这个算法类中封装了大量查找算法,该类代码将较复杂,维护较为困难

为了解决硬编码的缺点,可以定义一些独立的类来封装不同的算法,每一个类封装一个具体的算法,这就是策略模式

策略模式结构

在这里插入图片描述

策略模式角色:

  • 抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现
  • 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现
  • 环境(Context)类:持有一个策略类的引用,最终给客户端调用

可以看出,策略模式其实很简单,仅仅通过聚合、抽象继承的方法解耦合


具体实现

简单的实现出行策略的选择
在这里插入图片描述

package com.company.Behavioral.Strategy;
//抽象策略类
abstract class Strategy {
    protected String type;
    
    public abstract void travel();
}
//具体策略类:步行
class Walk extends Strategy{
    public Walk() {
        type = "Walk";
    }

    @Override
    public void travel() {
        System.out.println(" 选择出行方式 :"+type);
    }
}
//具体策略类:自行车
class Bicycle extends Strategy{
    public Bicycle() {
        type = "Bicycle";
    }

    @Override
    public void travel() {
        System.out.println(" 选择出行方式 :"+type);
    }
}
//具体策略类:公交车
class Bus extends Strategy{
    public Bus() {
        type = "Bus";
    }

    @Override
    public void travel() {
        System.out.println(" 选择出行方式 :"+type);
    }
}
//环境类
class TravelType{
    private Strategy type;

    public Strategy getType() {
        return type;
    }

    public void setType(Strategy type) {
        this.type = type;
    }
    public void travel(){
        type.travel();
    }
}
//客户类
class Client{
    public static void main(String[] args) {
        //创建环境类
        TravelType travelType = new TravelType();
        //选择一个出行策略:自行车
        Strategy bicycle = new Bicycle();
        travelType.setType(bicycle);
        //出行
        travelType.travel();
    }
}

策略模式是一个很简单的模式


策略模式优缺点

优点

  • 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为
  • 策略模式提供了管理相关的算法族的办法
  • 策略模式提供了可以替换继承关系的办法
  • 使用策略模式可以避免使用多重条件转移语句

缺点

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类
  • 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量

对于策略模式的思考

其实,看策略模式的结构,会发现挺简单的,就是定义好抽象策略类,实现多个具体策略对象,然后聚合到环境类中

  1. 策略模式需要客户明确需要的策略
  2. 策略模式仅仅是对算法的封装,根据客户的选择,提供策略的更新

策略模式与状态模式

他们两有点类似,一个是聚合状态对象,一个是聚合策略对象

区别在与:

  1. 客户需要明确选择哪个策略,而状态模式中客户无须关心具体的状态,只需知道在哪个状态调用哪个方法(策略模式客户类的压力更大)
  2. 策略模式环境类无须知道是哪个具体的策略;状态模式先需要确定一个初始状态,然后通过状态的方法来切换状态(状态模式状态的切换是在具体状态类中,策略模式是靠客户类切换策略)
  3. 状态模式强调的是不同状态下的不同行为;策略模式强调的是一个类的行为有多种实现策略,交由客户类选择一种

适用场景

从上面的策略模式的解析,可以总结策略模式的适用场景

  1. 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,动态的让一个对象在许多行为中选择一个
  2. 一个系统需要动态地在几种算法中选择一种
  3. 使用多重的条件选择语句来实现的一个类的行为的选择
  4. 不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性与安全性

总结

  • 策略模式:定义一系列算法并封装起来,让客户选择需要的算法
  • 策略模式有是三个角色:抽象策略类、具体策略类、环境类
  • 具体策略类是不同的算法封装;环境类聚合策略对象,交给客户调用
  • 策略类的优点:对开闭原则的支持,可以在不修改系统就基础上修改算法,提高了代码复用性;缺点:增加了客户类的负担,需要明确具体策略类,会增加系统中的类
  • 适用情况:系统中许多类的区别在与它们的行为;希望动态的让对象在许多行为中选择一个行为;避免使用难以维护的多重条件选择语句;希望封装算法和相关的数据结构
  • 策略模式较为简单,强调的是一个类的行为有多种实现策略,交由客户类选择一种
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值