加强检察门户网站建设情况/十大网络推广公司
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 Strategy getStrategy() {return strategy;}
public void setStrategy(Strategy strategy) {this.strategy = strategy;}
//由促销员展示促销活动给用户public void salesManShow() {strategy.show();}
}
测试类
public class Client {public static void main(String[] args) {//春节来了,使用春节促销活动SalesMan salesMan = new SalesMan(new StrategyA());//展示促销活动salesMan.salesManShow();
System.out.println("==============");//中秋节到了,使用中秋节的促销活动salesMan.setStrategy(new StrategyB());//展示促销活动salesMan.salesManShow();
System.out.println("==============");//圣诞节到了,使用圣诞节的促销活动salesMan.setStrategy(new StrategyC());//展示促销活动salesMan.salesManShow();}
}
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);elseTimSort.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 mergesif (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 descendingif (c.compare(a[runHi++], a[lo]) < 0) { // Descendingwhile (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)runHi++;reverseRange(a, lo, runHi);} else { // Ascendingwhile (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0)runHi++;}
return runHi - lo;}
}
上面的代码中最终会跑到 countRunAndMakeAscending()
这个方法中。我们可以看见,只用了compare方法,所以在调用Arrays.sort方法只传具体compare重写方法的类对象就行,这也是Comparator接口中必须要子类实现的一个方法。
相关文章:

设计模式(十八)----行为型模式之策略模式
1、概述 先看下面的图片,我们去旅游选择出行模式有很多种,可以骑自行车、可以坐汽车、可以坐火车、可以坐飞机。 作为一个程序猿,开发需要选择一款开发工具,当然可以进行代码开发的工具有很多,可以选择Idea进行开发&a…...

VUE3入门基础:input元素的type属性值说明
说明 在Vue 3中,<input>元素的type属性可以设置不同的类型,以适应不同的输入需求。 常见的type属性取值如下: text:默认值,用于输入文本。password:用于输入密码,输入内容会被隐藏。em…...

关于供应链,一文教你全面了解什么是供应链
什么是供应链?供应链是指产品生产和流通过程中所涉及的原材料供应商、生产商、分销商、零售商以及最终消费者等成员通过与上游、下游成员的连接 (linkage) 组成的网络结构。也即是由物料获取、物料加工、并将成品送到用户手中这一过程所涉及的企业和企业部门组成的一…...

Scope作用域简单记录分析
类型 singleton 单例作用域 prototype 原型作用域 request web作用域,请求作用域,生命周期跟request相同,请求开始bean被创建,请求结束bean被销毁 session web作用域,会话作用域,会话开始bean被创建,会话结束bean被销毁 application web作用域,应用程序作用域,应用程序创建…...

ChatGPT创作恋爱甜文
林欣是一个长相可爱、性格呆萌的小姑娘,她年纪轻轻就失去了父母,独自一人面对世界的冷漠和残酷。 虽然经历了这样的打击,但她并没有沉沦,反而更加努力地去生活。 她找到了一份服务员的工作,每天在餐厅里穿梭…...

贝叶斯优化及其python实现
贝叶斯优化是机器学习中一种常用的优化技术,其目的是在有限步数内寻找函数的最大值或最小值。它可以被视为在探索不同参数配置与观察这些配置结果之间寻求平衡点的过程。基本思想是将我们在过去的观察和体验,传递到下一个尝试中,从而在等待数…...

Lombok使用@Builder无法build父类属性
文章目录问题描述解决方案使用示例lombok Builder注解和build父类属性问题1、简介2.使用3、Builder注解对类做了什么?问题描述 实体类使用Lombok的Builder来实现Builder模式,但是如果使用了extend继承,则子类无法通过Builder来Build父类属性…...

Pixhawk RPi CM4 Baseboard 树莓派CM4安装Ubuntu20.04 server 配置ros mavros mavsdk
文章目录硬件安装Ubuntu Server20.04下载rpiboot工具下载imager刷写系统配置USB配置WIFI开机安装桌面配置wifi配置串口安装ROS安装mavros安装MAVSDK-PythonInternet设置最后参考: https://docs.holybro.com/autopilot/pixhawk-baseboards/pixhawk-rpi-cm4-baseboard…...

后端开发过程中的安全问题
安全问题是木桶效应,整个系统的安全等级取决于安全性最薄弱的那个模块。在写业务代码的时候,要从我做起,建立最基本的安全意识,从源头杜绝低级安全问题。 1、数据源头的安全处理 对于 HTTP 请求,我们要在脑子里有一个…...

基于Hyperledger Fabric的学位学历认证管理系统
基于Hyperledger Fabric的学位学历认证管理系统 项目源码:https://github.com/Pistachiout/Academic-Degree-BlockChain 一、选题背景 学历造假、认证造假等是一个全球日益普遍的现象,不仅对社会产生了巨大的负面影响,同时也极大增加了企业…...

jq条件判断验证,正则表达式
// 判断是否包含为至少8位及以上字符,大小写字母及特殊字符 jQuery.validator.addMethod("isPwd", function (value, element) { var pwdRegex new RegExp((?.*[0-9])(?.*[A-Z])(?.*[a-z])(?.*[^a-zA-Z0-9]).{8,30}); return this.optional(elemen…...

23.3.9打卡 AtCoder Beginner Contest 259
A题 题解 对于x特判一下就好 代码 void solve() {ll x,d;cin>>n>>m>>x>>t>>d;if(n>m){nmin(n,x);if(n<m){cout<<t;return;}cout<<(m-n)*dt;}else{mmin(m,x);cout<<(m-n)*dt;}return; }B 三角函数全还给高中老师了 题…...

JS - this指向
一 this 指向有哪几种 详细可见:https://juejin.cn/post/6844903805587619854 (文章归类this指向为四大类) https://www.jianshu.com/p/66eb9b21105d this是什么?this 就是一个指针,指向调用函数的对象。 1.默认绑定…...

低代码有哪些典型应用场景?
低代码有哪些典型应用场景? 低代码是一种全新的应用开发方式,它通过可视化的拖拽式界面,将传统的繁琐代码编写转化为简单的拖拽操作,让非技术人员也能够快速地开发出应用程序。 随着数字化转型的不断加速,低代码平台…...

Substrate 基础教程(Tutorials) -- 监控节点指标
Substrate 公开有关网络操作的度量。例如,您可以收集有关您的节点连接了多少个对等节点、您的节点使用了多少内存以及正在生成的块数量的信息。为了捕获和可视化Substrate节点公开的度量,您可以配置和使用Prometheus和Grafana等工具。本教程演示如何使用…...

lua table 详解
文章目录1.table 声明与访问2. table 的两种遍历方式 pairs 和 ipairs2.1 pairs2.2 ipairs2.3 例3.迭代器实现 ipairs 效果4.获取 table 长度4.1 #table 获取长度4.2 自定义函数获取 table 长度注意事项1.table 声明与访问 -- 初始化表 tbl {} -- 不可以是 tbl nil-- 赋值 -…...

Element表单嵌套树形表格的校验问题
普通嵌套 表单和表格是项目中最常见的项目,有时候就会遇到表格嵌套表单的情况,比如 这种形式的其实挺好处理的,如下: <el-form:model"states"ref"tableFormRef"label-width"80px"label-posit…...

1.webpack的基本使用
webpack是做工程化用的,并且可以对代码进行压缩(搞成min.js那样),处理浏览器端JS兼容性,性能优化 vue-cli与webpack作用相同 目录 1 基本使用 1.1 引入场景 1.2 安装webpack 1.3 配置webpack 1.4 使用webpack 2 webpack.config.…...

面试必看:谈谈你所了解的JVM调优,JVM性能调优总结
文章目录从面试角度来谈谈你了解的JVM调优GC调优的步骤1.确定目标:2.优化参数3.验收优化结果GC优化案例一、Major GC和Minor GC频繁优化Minor GC频繁问题:1.可以适当增大新生代的内存二、请求高峰期发生GC,导致服务可用性降低优化标记停顿时间…...

Pytorch优化器Optimizer
优化器Optimizer 什么是优化器 pytorch的优化器:管理并更新模型中可学习参数的值,使得模型输出更接近真实标签 导数:函数在指定坐标轴上的变化率 方向导数:指定方向上的变化率(二元及以上函数,偏导数&am…...

如何在MySQL 8中实现数据迁移?这里有一个简单易用的方案
文章目录前言一. 致敬IT领域的那些女性二. 进制方式安装MySQL2.1 下载软件包2.2 配置环境:2.2.1 配置yum环境2.2.2 配置安全前的系统环境2.3 开始安装2.4 初始化MySQL2.5 修改配置文件2.6 将MySQL设为服务并启动测试三. MySQL数据迁移总结前言 正好赶上IT女神节&am…...

java多线程(二三)并发编程:Callable、Future和FutureTask
一、Callable 与 Runnable 先说一下java.lang.Runnable吧,它是一个接口,在它里面只声明了一个run()方法: public interface Runnable {public abstract void run(); }由于run()方法返回值为void类型,所以在执行完任务之后无法返…...

day4分支和循环作业
基础题 根据输入的成绩的范围打印及格 或者不及格。 score 58 if score > 90:print(及格) else:print(不及格)根据输入的年纪范围打印成年或者未成年,如果年龄不在正常范围内(0~150)打印这不是人!。 age 52 if 0 < age < 18:print(未成年) elif 18 &l…...

轮毂要怎么选?选大还是选小?
随着改装车的越来越火爆,汽车轮毂可选择的款式也越来越多,90%的人换轮毂,首先选的就是外观。大轮毂的款式多,外形大气好看,运动感十足, 那是不是选大轮毂就可以呢?不是的,汽车轮毂要…...

RabbitMq 使用说明
1. 声明交换机和队列,以及交换机和队列绑定 import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.core.*; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.spr…...

Vue(10-20)
1Vue赋值方式 Object.defineProperty <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" conten…...

C++-对四个智能指针:shared_ptr,unique_ptr,weak_ptr,auto_ptr的理解
回答如下: C的智能指针是一种特殊类型的“指针”,其主要目的是自动跟踪内存分配和释放,以避免程序中出现内存泄露或空悬指针等问题,主要采用的技术是:借助于类的生命周期,当超出了类的作用域时,…...

uni-app中使用vue3语法详解
全局创建 app.use(createPina()).mount 全局方法 通过app.config.globalProperties.xxx可以创建 这里我们写了一个字符串翻转的全局方法 main.js里面添加一个全局方法 不要忘了加$ 否则会报错 // #ifdef VUE3 //导入创建app import { createSSRApp } from vue //导入创建ap…...

三十四、MongoDB PHP
PHP 语言可是使用 mongo.so ( Windows 下是 mongo.dll ) 扩展访问 MongoDB 数据库 MongoDB PHP 在各平台上的安装及驱动包下载请查看: PHP 安装 MongoDB 扩展驱动 如果你使用的是 PHP7,请移步: PHP7 MongoDB 安装与使用 PHP 连接 MongoDB 和 选择一个…...

浅拷贝和深拷贝的区别
浅拷贝和深拷贝 总结:浅拷贝对象数据共享,深拷贝是一个完全独立的对象,因此对象数据不共享。 浅拷贝(Shallow Copy) 浅拷贝是指创建一个新的对象,但是该新对象只是原始对象的一个副本。具体而言…...