【设计模式-4.1】行为型——策略模式

news2025/2/27 1:12:33

说明:本文介绍设计模式中的行为型设计模式中的,策略模式;

计算器

策略模式属于行为型设计模式,关注对象的行为。例如,目前有一个计算器类,可对两个数进行加减计算,如下:

(Calculator,计算器类)

/**
 * 计算器
 */
public class Calculator {
    /**
     * 加法
     */
    public static int add(int a, int b) {
        return a + b;
    }

    /**
     * 减法
     */
    public static int subtract(int a, int b) {
        return a - b;
    }
}

(Client,客户端,使用计算器的加法、减法)

/**
 * 客户端
 */
public class Client {
    public static void main(String[] args) {
        // 1. 加法
        System.out.println(Calculator.add(1, 2));

        // 2. 减法
        System.out.println(Calculator.subtract(1, 2));
    }
}

执行结果;

在这里插入图片描述

从这个简单的例子中就可以看出问题,扩展性差,如果需要增加乘法、减法或其他种种两个数运算的方法,都需要去修改计算器类。

我们可以考虑将计算器类中的计算方法抽出来称为一个抽象方法,让所有计算方法类都去实现这个接口,然后在计算器类中注入一个计算方法。如下:

(Computation,计算接口)

/**
 * 计算接口
 */
public interface Computation {

    /**
     * 计算方法
     */
    int compute(int num1, int num2);
}

(AddCompute,加法实现)

/**
 * 加法计算
 */
public class AddCompute implements Computation{

    @Override
    public int compute(int num1, int num2) {
        return num1 + num2;
    }
}

(SubCompute,减法实现)

/**
 * 减法计算
 */
public class SubCompute implements Computation{

    @Override
    public int compute(int num1, int num2) {
        return num1 - num2;
    }
}

(Calculator,计算器类,注入一个计算对象)

/**
 * 计算器
 */
public class Calculator {

    private Computation computation;

    public void setComputation(Computation computation) {
        this.computation = computation;
    }

    /**
     * 计算方法
     */
    public int compute(int num1, int num2) {
        return this.computation.compute(num1, num2);
    }
}

(Client,客户端,使用什么计算,就new什么计算方式)

/**
 * 客户端
 */
public class Client {
    public static void main(String[] args) {
        Calculator calculator = new Calculator();
        calculator.setComputation(new AddCompute());

        // 1. 加法
        System.out.println(calculator.compute(1, 2));

        // 2. 减法
        calculator.setComputation(new SubCompute());
        System.out.println(calculator.compute(1, 2));
    }
}

运行结果;

在这里插入图片描述

通过策略模式,将多种计算方法,从类中抽出来成一个个具体实现类,再创建一个统一的接口,使其实现该接口。这样,不论以后有多少计算方式,都可以创建具体实现类,实现其接口来添加,而不需要对现有的系统做改动。提高了扩展性。

登录方式

策略模式在项目开发中的一个应用是,对多种登录方式的整合。如下:

(LoginMethod,登录方式接口)

/**
 * 登录方式
 */
public interface LoginMethod {

    /**
     * 登录
     * @return
     */
    String login();
}

(PhoneServiceImpl,具体实现类,手机号登录,Bean名称:phone)

import org.springframework.stereotype.Service;

@Service("phone")
public class PhoneServiceImpl implements LoginMethod {
    @Override
    public String login() {
        return "手机号登录";
    }
}

(PasswordServiceImpl,具体实现类,账号密码登录,Bean名称:password)

import org.springframework.stereotype.Service;

@Service("password")
public class PasswordServiceImpl implements LoginMethod {
    @Override
    public String login() {
        return "账号密码登录";
    }
}

(WXLoginServiceImpl,具体实现类,微信登录,Bean名称:wx)

import org.springframework.stereotype.Service;

@Service("wx")
public class WXLoginServiceImpl implements LoginMethod {
    @Override
    public String login() {
        return "微信登录";
    }
}

(LoginController,登录Controller,传递登录类型)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping
public class LoginController {

    @Autowired
    private LoginService loginService;

    @PostMapping("/login")
    public String login(String loginType) {
        return loginService.executeLogin(loginType);
    }
}

(LoginService,登录接口)

public interface LoginService {

    /**
     * 根据登录方式执行登录
     *
     * @param loginType
     * @return
     */
    String executeLogin(String loginType);
}

(LoginServiceImpl,登录实现类,使用applicationContext.getBean方法获取对应的登录具体实现类,执行其方法,执行对应的登录方式

import com.hezy.service.LoginMethod;
import com.hezy.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

/**
 * 登录服务实现类
 */
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public String executeLogin(String loginType) {
        LoginMethod loginMethod = (LoginMethod) applicationContext.getBean(loginType);
        return loginMethod.login();
    }
}

启动项目,使用apifox查看执行效果;

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

当然,这只是一个框架。实际开发,登录需要的信息很多。登录方式肯定是作为一个字段值传入的,如DTO中的一个属性值,具体的登录实现也是需要编写大量代码的,账号密码登录的是去查数据库,手机号登录的是去实现第三方SDK,微信登录的是实现微信登录的SDK。

以上就是策略模式的实现,通过两个例子可以看出,策略模式是对多种解决方案的封装,通过将解决方案设计成接口>具体实现类组合的方式,提高了系统的扩展性,非常实用。

总结

本文参考《设计模式的艺术》、《秒懂设计模式》两书

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Innodb数据空间占用探索

了解数据存储空间占用,可以更方便我们再企业中对于数据库相关优化做评估。 一、查看当前数据表空间占用信息 首先这里准备一张数据库表约2.3w数据量: CREATE TABLE project (tenantsid bigint(20) NOT NULL DEFAULT 0 COMMENT 租户ID,project_id bigi…

Redis RDB

基于内存的 Redis, 数据都是存储在内存中的。 那么如果重启的话, 数据就会丢失。 为了解决这个问题, Redis 提供了 2 种数据持久化的方案: RDB 和 AOF。 RDB 是 Redis 默认的持久化方案。当满足一定条件的时候, 会把当前内存中的数据写入磁盘, 生成一个快照文件 dump.rdb。Redi…

thinkphp 5.1 对数据库查出来的字段进行预处理

比如数据库的设计是下面这样子&#xff1a; 我想展示的是这个样子&#xff1a; 前端可以处理。 Think PHP的处理方式&#xff1a; 定义属性 &#xff1a; $this->customize 任意值;//这里的之没有作用 <?phpnamespace app\hs\controller\shop;use app\daogou\mo…

C++ list容器

文章目录 C++ list容器list基本概念list构造函数list 赋值和交换list 大小操作list 插入和删除list 数据存取list 反转和排序排序案例C++ list容器 list基本概念 功能:将数据进行链式存储 链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中…

ipvlan介绍

最近使用docker&#xff0c;涉及到需要跨多台物理机部署系统&#xff0c;查了好多资料&#xff0c;最后查到了ipvlan。那什么是vlan&#xff0c;什么又是ipvlan。 交换机层面的vlan&#xff0c;是按802.1Q规范&#xff0c;在链路层中加了4字节的标识vlan的数据&#xff0c;交换…

12.1 二叉树简单题

101. 对称二叉树 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true 思路&#xff1a;对称二叉树 有一个特点是以 中左右顺序遍历左子树的结果会等于 中右左顺序遍历右子树的结果…

Linux的基本指令(4)

目录 20.tar指令&#xff08;重要&#xff09;&#xff1a;打包/解包&#xff0c;不打开它&#xff0c;直接看内容 21.bc指令 22.uname –r指令&#xff1a; 23.重要的几个热键[Tab],[ctrl]-c, [ctrl]-d 20.tar指令&#xff08;重要&#xff09;&#xff1a;打包/解包&#…

Hdoop学习笔记(HDP)-Part.08 部署Ambari集群

目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …

深度学习(四):pytorch搭建GAN(对抗网络)

1.GAN 生成对抗网络&#xff08;GAN&#xff09;是一种深度学习模型&#xff0c;由两个网络组成&#xff1a;生成器&#xff08;Generator&#xff09;和判别器&#xff08;Discriminator&#xff09;。生成器负责生成假数据&#xff0c;而判别器则负责判断数据是真实的还是 f…

cnpm 安装后无法使用怎么办?

问题的原因 cnpm 安装成功&#xff0c;但是却无法使用&#xff0c;一般分为两种情况&#xff0c;一种是提示无法执行命令&#xff0c;另一种是可以执行但是执行时报错&#xff0c;下面分别说明遇到这两种情况的解决方案。 解决方案 问题一&#xff1a;无法执行相关命令 首先…

Docker快速入门(docker加速,镜像,容器,数据卷常见命令操作整理)

Docker本质是将代码所需的环境依赖进行打包运行,而在Docker中最重要的是镜像和容器 镜像:可以简单地理解为每启动一个docker镜像就会占用计算机一个进程,这个进程和另外起的docker镜像的进程是相互独立的,以数据库为例,每个镜像都会copy一份数据库,在他所在的进程中.别的镜像在…

根文件系统构建-对busybox进行配置

一. 简介 本文来学习 根文件系统的制作中&#xff0c;关于 busybox的配置。 本文继上一篇 busybox中文支持的设置&#xff0c;地址如下&#xff1a; 根文件系统构建-busybox中文支持-CSDN博客 二. 根文件系统构建-busybox配置 1. 配置 busybox 与我们编译 Uboot 、 Lin…

DBeaver 社区版(免费版)下载、安装、解决驱动更新出错问题

DBeaver 社区版&#xff08;免费版&#xff09; DBeaver有简洁版&#xff0c;企业版&#xff0c;旗舰版&#xff0c;社区版&#xff08;免费版&#xff09;。除了社区版&#xff0c;其他几个版本都是需要付费的&#xff0c;当然相对来说&#xff0c;功能也要更完善些&#xff…

HashMap源码全面解析

注&#xff1a;本篇文章是在JDK1.8版本源码进行分析。 一、概述 HashMap 是基于哈希表的 Map接口的实现&#xff0c;是以 key-value 存储形式存在&#xff0c;即主要用来存储键值对。 HashMap的类图&#xff1a; HashMap继承抽象类AbstractMap&#xff0c;实现了Map、Clonea…

select选择框里填充图片,下拉选项带图片

遇到一个需求&#xff0c;选择下拉框选取图标&#xff0c;填充到框里 1、效果展示 2、代码 <el-form-item label"工种图标" class"Form_icon Form_label"><el-select ref"select" :value"formLabelAlign.icon" placeholder&…

2023年第十二届数学建模国际赛小美赛B题工业表面缺陷检测求解分析

2023年第十二届数学建模国际赛小美赛 B题 工业表面缺陷检测 原题再现&#xff1a; 金属或塑料制品的表面缺陷不仅影响产品的外观&#xff0c;还可能对产品的性能或耐久性造成严重损害。自动表面异常检测已经成为一个有趣而有前景的研究领域&#xff0c;对视觉检测的应用领域有…

PyQt6 QRadioButton单选按钮控件

​锋哥原创的PyQt6视频教程&#xff1a; 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计33条视频&#xff0c;包括&#xff1a;2024版 PyQt6 Python桌面开发 视频教程(无废话…

Opencv框选黑色字体进行替换(涉及知识点:selectROI,在控制台输入字体大小,颜色,内容替换所选择的区域)

import cv2 from PIL import Image,ImageDraw,ImageFont import numpy as npimg_path ../img/ img_clean_path ../img_clean/ name xiao_ben suf .pngimg cv2.imread(img_pathnamesuf) cv2.imshow(original, img)# 选择ROI roi cv2.selectROI(windowName"original&q…

Linux多核飞控

Linux多核飞控是一种基于多核处理器构建的飞控系统&#xff0c;用于控制飞行器的飞行。这种飞控系统使用Linux操作系统作为主要的控制平台&#xff0c;可以支持多个处理器核心同时工作&#xff0c;以实现更高的性能和更快的响应速度。 Linux通常用于具有较高计算量和较大内存需…

Python读取json数据导出到Excel

一、JSON字符串转换为Python对象 导入Python的json模块。该模块包含两个重要的功能-loads和load,读取JSON文件&#xff0c;并将JSON数据解析为Python数据&#xff0c;除了JSON&#xff0c;我们还需要Python的原生函数open()。一般loads用于读取JSON字符串&#xff0c;而load()用…