策略模式详解

策略模式

1 概述

先看下面的图片,我们去旅游选择出行模式有很多种,可以骑自行车、可以坐汽车、可以坐火车、可以坐飞机。

请添加图片描述

作为一个程序猿,开发需要选择一款开发工具,当然可以进行代码开发的工具有很多,可以选择Idea进行开发,也可以使用eclipse进行开发,也可以使用其他的一些开发工具。

请添加图片描述

定义:

​ 该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

2 结构

策略模式的主要角色如下:

  • 抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
  • 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为。
  • 环境(Context)类:持有一个策略类的引用,最终给客户端调用。

3 案例实现

【例】促销活动

一家百货公司在定年度的促销活动。针对不同的节日(春节、中秋节、圣诞节)推出不同的促销活动,由促销员将促销活动展示给客户。类图如下:

请添加图片描述

代码如下:

定义百货公司所有促销活动的共同接口

public interface Strategy {
    void show();
}

定义具体策略角色(Concrete Strategy):每个节日具体的促销活动

//为春节准备的促销活动A
public class StrategyA implements Strategy {

    public void show() {
        System.out.println("买一送一");
    }
}

//为中秋准备的促销活动B
public class StrategyB implements Strategy {

    public void show() {
        System.out.println("满200元减50元");
    }
}

//为圣诞准备的促销活动C
public class StrategyC implements Strategy {

    public void show() {
        System.out.println("满1000元加一元换购任意200元以下商品");
    }
}

定义环境角色(Context):用于连接上下文,即把促销活动推销给客户,这里可以理解为销售员

public class SalesMan {                        
    //持有抽象策略角色的引用                              
    private Strategy strategy;                 
                                               
    public SalesMan(Strategy strategy) {       
        this.strategy = strategy;              
    }                                          
                                               
    //向客户展示促销活动                                
    public void salesManShow(){                
        strategy.show();                       
    }                                          
}                                              

4 优缺点

1、优点:

  • 策略类之间可以自由切换

    由于策略类都实现同一个接口,所以使它们之间可以自由切换。

  • 易于扩展

    增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“

  • 避免使用多重条件选择语句(if else),充分体现面向对象设计思想。

2、缺点:

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

5 使用场景

  • 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中。
  • 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支移入它们各自的策略类中以代替这些条件语句。
  • 系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。
  • 系统要求使用算法的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关的数据结构。
  • 多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为。

6 JDK源码解析

Comparator 中的策略模式。在Arrays类中有一个 sort() 方法,如下:

public class Arrays{
    public static <T> void sort(T[] a, Comparator<? super T> c) {
        if (c == null) {
            sort(a);
        } else {
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a, c);
            else
                TimSort.sort(a, 0, a.length, c, null, 0, 0);
        }
    }
}

Arrays就是一个环境角色类,这个sort方法可以传一个新策略让Arrays根据这个策略来进行排序。就比如下面的测试类。

public class demo {
    public static void main(String[] args) {

        Integer[] data = {12, 2, 3, 2, 4, 5, 1};
        // 实现降序排序
        Arrays.sort(data, new Comparator<Integer>() {
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        System.out.println(Arrays.toString(data)); //[12, 5, 4, 3, 2, 2, 1]
    }
}

这里我们在调用Arrays的sort方法时,第二个参数传递的是Comparator接口的子实现类对象。所以Comparator充当的是抽象策略角色,而具体的子实现类充当的是具体策略角色。环境角色类(Arrays)应该持有抽象策略的引用来调用。那么,Arrays类的sort方法到底有没有使用Comparator子实现类中的 compare() 方法吗?让我们继续查看TimSort类的 sort() 方法,代码如下:

class TimSort<T> {
    static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
                         T[] work, int workBase, int workLen) {
        assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;

        int nRemaining  = hi - lo;
        if (nRemaining < 2)
            return;  // Arrays of size 0 and 1 are always sorted

        // If array is small, do a "mini-TimSort" with no merges
        if (nRemaining < MIN_MERGE) {
            int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
            binarySort(a, lo, hi, lo + initRunLen, c);
            return;
        }
        ...
    }   
        
    private static <T> int countRunAndMakeAscending(T[] a, int lo, int hi,Comparator<? super T> c) {
        assert lo < hi;
        int runHi = lo + 1;
        if (runHi == hi)
            return 1;

        // Find end of run, and reverse range if descending
        if (c.compare(a[runHi++], a[lo]) < 0) { // Descending
            while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)
                runHi++;
            reverseRange(a, lo, runHi);
        } else {                              // Ascending
            while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0)
                runHi++;
        }

        return runHi - lo;
    }
}

上面的代码中最终会跑到 countRunAndMakeAscending() 这个方法中。我们可以看见,只用了compare方法,所以在调用Arrays.sort方法只传具体compare重写方法的类对象就行,这也是Comparator接口中必须要子类实现的一个方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/632210.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

sqlserver正确配置

一、启动sql server 服务&#xff0c;右键–>启动 二、设置网络协议 三、启动sa用户 1.使用windows用户验证登录Studio工具 2.选择安全性–>登录名–>sa, 右键选择属性 3.设置服务器身份验证模式 4.导入数据库文件

在面对各种问题时,我们应该如何进行数据分析

python数据分析汇总 前言一、对比分析概念特征类型案例Matplotlib的颜色字母对照表解决遇到未知函数 二、相关性分析概念类型案例一案例二 三、时间序列分析概念类型案例 四、回归分析概念类型案例一案例二案例三 五、决策树概念计算过程案例 六、主成分分析概念计算过程案例 七…

【会议征稿,ACM出版】第四届人工智能,大数据与算法国际学术会议 (CAIBDA 2024, 7/5-7)

由河南省科学院、河南大学主办&#xff0c;河南省科学院智慧创制研究所、河南大学学术发展部、河南大学人工智能学院承办的第四届人工智能&#xff0c;大数据与算法国际学术会议 (CAIBDA 2024)将于2024年7月5-7日于中国郑州隆重举行。CAIBDA 2024致力于为人工智能&#xff0c;大…

数据库设计大题详解

大题一&#xff1a;画E-R图&#xff08;概念结构设计&#xff09; 实体就是具体的物品&#xff0c;关系就是实体之间的关系&#xff0c;属性就是特征&#xff0c;内涵的意思 简单的小栗子&#xff1a; 1对1&#xff0c;1对n&#xff0c;n对m&#xff0c;自己考虑两者存在这个关…

ubuntu虚拟机的 网卡不见了?

通过 ifconfig 命令查找不到自己的虚拟机上网网卡了,虚拟机的上网网卡名字是ens33 发现只有一个本地回环地址 执行如下两条指令可恢复网卡 sudo dhclient ens33#获取ip sudo ifconfig ens33#查看ip 再次通过ifconfig查看网卡信息

HP5V80、HP5V105、HP3V28电比例驱动柱塞泵放大器

HP5V80、HP5V105、HP3V28、HP3V45、HP3V60、HP3V80、HP3V125、HP3V140带电比例控制泵放大器&#xff0c;变排量泵的排量可通过由BEUEC比例放大器输出到比例电磁阀电流变化而进行调整&#xff0c;控制电流范围为300mA至800mA(24VDC)或600mA至1600mA(12VDC)。主要适合应用于工程机…

植物大战僵尸杂交版(含下载方式)

最近时间&#xff0c;一款很火的植物大战僵尸杂交版火爆出圈&#xff0c;在玩家之间疯狂扩散。各种奇特的杂交组合让游戏变得更加有趣。 游戏介绍 植物大战僵尸杂交版是一款将《植物大战僵尸》和植物杂交概念结合在一起的独特塔防策略游戏。它将《植物大战僵尸》中的植物与进行…

沉钒废水回收钒

沉钒废水处理与钒回收的重要性 沉钒废水是含钒元素的特殊废水&#xff0c;钒在工业生产中广泛应用&#xff0c;但其排放造成资源浪费与环境威胁。为实现钒的有效回收&#xff0c;研究和实践了多种处理技术。 沉钒废水处理技术 1. 化学沉淀法&#xff1a;添加沉淀剂&#xff…

使用OverPy API批量获取OpenStreetMap(OSM)城市路网png图片和svg矢量图

在地理信息系统&#xff08;GIS&#xff09;和数据可视化领域&#xff0c;获取城市路网的图像对于分析和展示城市交通结构至关重要。OpenStreetMap (OSM) 是一个免费且开放的地理数据源&#xff0c;而OverPy 是一个用于访问OSM数据的Python库。本文将详细介绍如何使用OverPy AP…

push to origin/master was rejected解决方案之一

如果你是git小白&#xff0c;并且其他帖子的方法都不行&#xff0c;可以一试 在你的远程库&#xff08;我这个是gitee&#xff09;设置中的邮箱设置里不勾这个选项 然后就没有然后了。

仓库数据同步难题如何轻松破解?

一、客户介绍 某食品科技有限公司&#xff0c;是一家集研发、生产、销售于一体的现代化食品科技企业。公司的经营范围广泛&#xff0c;涵盖饮料生产、食品生产、食品经营&#xff08;销售散装食品&#xff09;、食品互联网销售以及货物进出口等多个领域。通过数字化冷链物流监…

ALV 图标显示

前言 在ABAP ALV中&#xff0c;使用fieldcat来定义列表中每个字段的显示属性&#xff0c;包括图标&#xff08;Icon&#xff09;的显示。图标可以在ALV列表中为特定列的行或标题添加图形元素&#xff0c;以增强视觉提示或传达附加信息。 ICON查询 图标的名称用事务码”ICON“进…

【无标题】海图微电子产品

一、HT2300 1、产品介绍 HT2300在全分辨率 (1920 H 1080 V) 下&#xff0c;它们的帧率可达2500fps。加上全局快门像素和低噪声等特性&#xff0c;可满足对高分辨率&#xff0c;高速CMOS图像传感器的需求&#xff0c;适用于科学研究&#xff0c;工业检测和数字影视中高速视频捕捉…

【数据链路层】以太网帧包解析

文章目录 以太网的帧结构解析数据链路层信息 以太网的帧结构 使用抓包工具&#xff0c;查看数据链路层信息&#xff1a; 解析数据链路层信息 &#xff08;1&#xff09;协议类型&#xff1a;代表上层的协议 &#xff08;IP00800 ARP00806 IPv686DD &#xff09; 如图中所示&a…

2024 Google I/O - 提前窥探 Android 15 的新功能与适配

今年年初就简单介绍过 Android 15 预览版 的相关内容&#xff0c;而昨天 Google I/O 宣布了 Android 15 Beta2&#xff0c;作为第二个 Beta 版本 &#xff0c;它已经基本接近它未来的样子&#xff0c;毕竟下个版本就是 Platform Stability 了&#xff0c;所以让我们提前来一睹 …

电脑恢复出厂设置怎么弄?让你的电脑焕然一新!

电脑恢复出厂设置是一种常见的操作&#xff0c;它可以帮助用户将电脑恢复到初始状态&#xff0c;清除所有数据和设置&#xff0c;使其恢复到出厂时的状态。这对于解决系统故障、清除个人数据以及重新配置电脑等情况非常有用。可是电脑恢复出厂设置怎么弄呢&#xff1f;本文将介…

网络安全快速入门(十三)linux及vmware软件的网络配置

13.1 前言 在通过我们前面的了解&#xff0c;我们现在已经对Linux的基础知识有了大致的了解&#xff0c;今天我们来大概讲一下关于linux系统及vmware的网络配置问题&#xff0c;在这之前&#xff0c;我们需要对网络有一个大概的认识和了解&#xff0c;话不多说&#xff0c;我们…

「AI模型瘦身术」——知识蒸馏技术综述

使用KD原因 遇到问题&#xff1a;从产业发展的角度来看工业化将逐渐过渡到智能化&#xff0c;边缘计算逐渐兴起预示着 AI 将逐渐与小型化智能化的设备深度融合&#xff0c;这也要求模型更加的便捷、高效、轻量以适应这些设备的部署。 解决方案&#xff1a;知识蒸馏技术 知识…

记一次:mysql统计的CAST函数与json字段中的某个字段

前言&#xff1a;因为需求的问题&#xff0c;会遇到将某个json存入到一个字段中&#xff0c;但在统计的时候&#xff0c;又需要将这个json中的某个字段作为条件来统计&#xff0c;所以整理了一下cast函数和json中某个字段的条件判断 一、浅谈mysql的json 1.1 上例子 SELECTli…