【行为型模式】策略模式

一、策略模式概述

        策略模式(又叫政策Policy模式),属于对象行为模式下的:Strategy类提供了可插入式(Pluggable)算法的实现方案。

        策略模式的定义-意图:定义一系列算法,将每一个算法封装起来,并让它们互相替换。策略模式让算法可以独立于使用它的客户变化。

        模式策略的优缺点

  • 优点
    • 1.提供了对开闭(开时针对扩展功能是开放的,闭对修改功能是关闭的)原则的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为;
    • 2.提供了管理相关的算法族的办法;
    • 3.提供了一种可以替换继承关系的办法;
    • 4.可以避免多重条件选择语句;
    • 5.提供了一种算法的复用机制,不同环境类可以方便地复用策略类。(单一职责)       
  • 缺点
    • 1.客户端必须知道所有的策略类,并自行决定使用哪一个策略类;
    • 2.将造成系统产生很多具体策略类;
    • 3.无法同时在客户端使用多个策略类。
  • 适用环境
    • 1.一种系统需要动态地在几种算法中选择一种;
    • 2.避免使用难以维护的多重条件选择语句;
    • 3.不希望客户端知道复杂的、与算法相关的数据结构,提高算法的保密性与安全。

二、代码实现

        策略模式的结构,包含3个角色:

  • 1.环境(Context)角色:持有一个Strategy类的引用;
  • 2.抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需要的接口;
  • 3.具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
2.1 售票策略
        2.1.1 抽象策略角色(接口实现,接口名为Discount)
package Strategy.Mticket;
//抽象策略,打折
public interface Discount {public double calculate(double price);
}
        2.1.2 具体策略角色:儿童票(ChildrenDiscount)、学生票(StudentDiscount)、VIP票(VIPDiscount)
package Strategy.Mticket;
//具体策略,儿童票
public class ChildrenDiscount implements Discount {//代码的可维护性使用全局变量private final double DISCOUNT = 10 ;@Overridepublic double calculate(double price) {// TODO 自动生成的方法存根if(price>=20) {System.out.println("儿童票:");return price - DISCOUNT;}else {return price;}		}
}
package Strategy.Mticket;
//具体策略,学生票
public class StudentDiscount implements Discount {private final double DISCOUNT=0.8;@Overridepublic double calculate(double price) {// TODO 自动生成的方法存根System.out.println("学生票:");return price * DISCOUNT;}
}
package Strategy.Mticket;
//具体策略,VIP票
public class VIPDiscount implements Discount {private final double DISCOUNT=0.5;@Overridepublic double calculate(double price) {// TODO 自动生成的方法存根System.out.println("VIP票:");System.out.println("增加积分:");return price * DISCOUNT;}
}
        2.1.3 环境角色:电影票(MovieTicket)
package Strategy.Mticket;
//环境类,电影票
public class MovieTicket {private double price;private Discount discount; //对抽象折扣类的引用/*public double getPrice() {//调用折扣类的折扣价计算方法//rerurn折后价return discount.calculate(this.price);}*/public double getPrice() {return price;}public double getDiscountPrice() {return discount.calculate(this.price);}public void setPrice(double price) {this.price = price;}public Discount getDiscount() {return discount;}//注入一个折扣类public void setDiscount(Discount discount) {this.discount = discount;}}
        2.1.4 main方法调用实现策略模式
package Strategy.Mticket;public class Client2 {public static void main(String[] args) {// TODO 自动生成的方法存根MovieTicket mt =new MovieTicket();mt.setPrice(60.0);//mt.setDiscount(new VIPDiscount());//Discount ds =new StudentDiscount();Discount ds =new VIPDiscount();mt.setDiscount(ds);System.out.println("折后价为:"+mt.getDiscountPrice());}}
        2.1.5 实例化工具代码(XMLUtil)

        如果想利用配置文件来实例化对象,可以减轻对代码的更改,直接对配置文件修改就可以。具体代码如下:

package Strategy.Mticket;import java.io.*;
import javax.xml.parsers.*;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;
//实例化对象,配置文件就是想要s实例的对象
public class XMLUtil {//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象public static Object getBean() {try {//创建DOM文档对象DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = dFactory.newDocumentBuilder();Document doc;//file里就是配置文件doc =builder.parse(new File("src//Strategy//Mticket//config2.xml"));//获取包含类名的文本节点NodeList nl =doc.getElementsByTagName("className");//item这是一个数组,就是调用xml文件中的className内容Node classNode=nl.item(0).getFirstChild();//cName为类名,getNodeValue为字符串类型方法String cName = classNode.getNodeValue();//通过类名生成实例对象并将其返回//forName为java的反射技术Class c = Class.forName(cName);Object obj = c.newInstance();return obj;}catch(Exception e) {e.printStackTrace();return null;}}
}
        2.1.6 XML配置文件(config.xml)
<?xml version="1.0" encoding="UTF-8"?>
<config>
<className>Strategy.Mticket.VIPDiscount</className>
</config>
        2.1.7 利用配置文件的main方法实现
package Strategy.Mticket;public class Client {public static void main(String[] args) {// TODO 自动生成的方法存根MovieTicket mt = new MovieTicket();double originalPrice = 60.0;double currentPrice;mt.setPrice(originalPrice);System.out.println("原始价格为:"+originalPrice);System.out.println("-----------------------------");Discount discount;//读取配置文件并反射生成具体折扣对象//强转discount =(Discount)XMLUtil.getBean();mt.setDiscount(discount);//注入折扣对象currentPrice = mt.getDiscountPrice();System.out.println("折后价为:"+currentPrice);}}
        2.1.8 UML图 

2.2 鸭子行为策略

进阶版策略模式

甲方:我需要一堆鸭子,红色的,绿色的,黑色的,还要会飞!还要会叫!

乙方:明白,N种鸭子就像电影票一样,只要继承了我的Duck类然后重写,就搞定一切!

甲方:哦吼!为什么橡皮鸭子会在天上飞?

乙方:无脑继承类是不对的!!!

解决方案:只用封装,继承好像不行,好像还有一个多态(接口)?是不是可以把飞这个行为定义成接口,然后把这个接口, 放到鸭子基类里面去!

真正的策略模式核心即:封装行为,依赖接口,组合代替继承!

        2.2.1 抽象策略角色(鸭子抽象基类Duck、飞行为接口FlyBehavior、叫行为接口QuackBehavior)
package Strategy.behavior;
//抽象策略,鸭子
public abstract class Duck {/*** 飞行行为是动态的,可能会变的,因此抽成多个接口的组合,而不是让Duck类继承*///接口变量FlyBehavior flybehavior;//面向接口编程QuackBehavior quackBehavior;public void createfly() {flybehavior.fly();}/*** 每个鸭子的叫声不同,抽象成接口*/public void createquack() {quackBehavior.quack();}//为了测试方便public void test() {this.display();this.createquack();this.createfly();this.swim();}public void swim() {System.out.println("我在游泳");}public abstract void display();
}
package Strategy.behavior;
// 飞行为
public interface FlyBehavior {public void fly();
}
package Strategy.behavior;
//叫行为
public interface QuackBehavior {public void quack();
}
        2.2.2 具体策略角色(用翅膀飞FlyWithWings、不会飞FlyNoWay、会叫Quack、不会叫MuteQuack、摩擦声Squeak)
package Strategy.behavior;
//会飞
public class FlyWithWings implements FlyBehavior {@Overridepublic void fly() {// TODO 自动生成的方法存根System.out.println("我在飞,用翅膀飞");}}
package Strategy.behavior;public class FlyNoWay implements FlyBehavior {
//不会飞@Overridepublic void fly() {// TODO 自动生成的方法存根}}
package Strategy.behavior;
//会叫
public class Quack implements QuackBehavior {@Overridepublic void quack() {// TODO 自动生成的方法存根System.out.println("我在呱呱叫");}}
package Strategy.behavior;
//不会叫
public class MuteQuack implements QuackBehavior {@Overridepublic void quack() {// TODO 自动生成的方法存根}
}
package Strategy.behavior;
//摩擦声
public class Squeak implements QuackBehavior {@Overridepublic void quack() {// TODO 自动生成的方法存根System.out.println("我不会呱呱叫,但是我能发出橡皮与空气的摩擦声");}}
        2.2.3 环境角色(诱饵鸭DecoyDuck、绿头会飞鸭MallardDuck、红头会飞鸭RedHeadDuck、橡皮鸭RubberDuck)
package Strategy.behavior;
//诱饵鸭
public class DecoyDuck extends Duck{public DecoyDuck() {quackBehavior =new MuteQuack();flybehavior =new FlyNoWay();}@Overridepublic void display() {// TODO 自动生成的方法存根sSystem.out.println("我是一只诱饵鸭");}
}
package Strategy.behavior;
//绿头会飞鸭
public class MallardDuck extends Duck {public  MallardDuck() {quackBehavior=new Quack();flybehavior=new FlyWithWings();}@Overridepublic void display() {// TODO 自动生成的方法存根System.out.println("我是一只绿头,灰色羽毛的鸭子");}
}
package Strategy.behavior;
//红头会飞鸭
public class RedHeadDuck extends Duck {public RedHeadDuck() {quackBehavior=new Quack();flybehavior=new FlyWithWings();}@Overridepublic void display() {// TODO 自动生成的方法存根System.out.println("我是一只红头,灰色羽毛的鸭子");}
}
package Strategy.behavior;
//橡皮鸭
public class RubberDuck extends Duck {public RubberDuck(){quackBehavior=new Squeak();flybehavior =new FlyNoWay();}@Overridepublic void display() {// TODO 自动生成的方法存根System.out.println("我是一只黄色的橡皮鸭");}
}
        2.2.4 main方法调用实现策略模式
package Strategy.behavior;public class Test {public static void main(String[] args) {// TODO 自动生成的方法存根Duck ducks[]=new Duck[4];ducks[0]=new MallardDuck();ducks[1]=new RedHeadDuck();ducks[2]=new RubberDuck();ducks[3]=new DecoyDuck();ducks[0].test();ducks[1].test();ducks[2].test();ducks[3].test();			}
}
        2.2.5 UML图

三、代码结构

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

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

相关文章

Mybatis常用注解说明

MyBatisPlus 常用注解说明 TableName(opens new window) 描述&#xff1a;表名注解&#xff0c;标识实体类对应的表 使用位置&#xff1a;实体类 TableName("sys_user") public class User {private Long id;private String name;private Integer age;private Strin…

实用图像视频修复工具:完善细节、提高分辨率 | 开源日报 No.225

xinntao/Real-ESRGAN Stars: 25.6k License: BSD-3-Clause Real-ESRGAN 是一个旨在开发实用的图像/视频恢复算法的项目。 该项目主要功能、关键特性和核心优势包括&#xff1a; 提供动漫视频小模型和动漫插图模型支持在线 Colab 演示和便携式 Windows/Linux/MacOS 可执行文件…

如何利用纯前端技术,实现一个网页版视频编辑器?

纯网页版视频编辑器 一、前言二、功能实现三、所需技术四、部分功能实现4.1 素材预设4.2 多轨道剪辑 一、前言 介绍&#xff1a;本篇文章打算利用纯前端的技术&#xff0c;来实现一个网页版的视频编辑器。为什么突然想做一个这么项目来呢&#xff0c;主要是最近一直在利用手机…

OpenCV基本图像处理操作(四)——傅立叶变换

傅里叶变换的作用 高频&#xff1a;变化剧烈的灰度分量&#xff0c;例如边界 低频&#xff1a;变化缓慢的灰度分量&#xff0c;例如一片大海 滤波 低通滤波器&#xff1a;只保留低频&#xff0c;会使得图像模糊 高通滤波器&#xff1a;只保留高频&#xff0c;会使得图像细节…

Golang | Leetcode Golang题解之第31题下一个排列

题目&#xff1a; 题解&#xff1a; func nextPermutation(nums []int) {n : len(nums)i : n - 2for i > 0 && nums[i] > nums[i1] {i--}if i > 0 {j : n - 1for j > 0 && nums[i] > nums[j] {j--}nums[i], nums[j] nums[j], nums[i]}reverse…

Day 14 网络协议

常见网络设备&#xff1a;交换机 路由器 中继器 多协议网关&#xff08;路由器的前身&#xff09; 交换机&#xff1a;用于连接统一网络的设备&#xff0c;实现内网设备通信。 从广义上分为&#xff1a;局域网交换机&#xff0c;广域网交换机 从网络构成分为&#xff1a;接…

Jenkins配置windows/linux从节点

背景&#xff1a; 环境&#xff1a;jenkins环境&#xff08;Ubuntu&#xff09; 节点机器&#xff1a;Linux、Windows 前置条件&#xff1a; 节点机器&#xff1a;安装java、allure、python 1 Linux节点管理机器添加 1.1 系统管理->节点列表->New Node 1.2 节点配置…

「GO基础」文件名规范、关键字与标识符

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

元数据管理Atlas

文章目录 一、Atlas概述1、Atlas入门2、Atlas架构原理 二、Atlas安装1、安装环境准备1.1 安装Solr-7.7.31.2 Atlas2.1.0安装 2、Atlas配置2.1 Atlas集成Hbase2.2 Atlas集成Solr2.3 Atlas集成Kafka2.4 Atlas Server配置2.5 Kerberos相关配置2.6 Atlas集成Hive 3、Atlas启动 三、…

用海外云手机高效率运营TikTok!

很多做国外社媒运营的公司&#xff0c;想要快速引流&#xff0c;往往一个账号是不够的&#xff0c;多数都是矩阵养号的方式&#xff0c;运营多个TikToK、Facebook、Instagram等账号&#xff0c;慢慢沉淀流量变现&#xff0c;而他们都在用海外云手机这款工具&#xff01; 海外云…

知识管理系统(KMS):一文扫盲,能和chatGPT相融吗?

一、什么是KMS&#xff0c;有什么作用 KMS&#xff08;Knowledge Management System&#xff09;知识管理系统是一种用于组织、存储、共享和利用知识的软件系统或平台。它旨在帮助组织有效地管理和利用内部和外部的知识资源&#xff0c;以支持决策、创新和持续学习。 KMS知识管…

华为云CodeArts IDE For Python 快速使用指南

CodeArts IDE 带有 Python 扩展&#xff0c;为 Python 语言提供了广泛的支持。Python 扩展可以利用 CodeArts IDE 的代码补全、验证、调试和单元测试等特性&#xff0c;与多种 Python 解释器协同工作&#xff0c;轻松切换包括虚拟环境和 conda 环境的 Python 环境。本文简要概述…

OpenCV基本图像处理操作(三)——图像轮廓

轮廓 cv2.findContours(img,mode,method) mode:轮廓检索模式 RETR_EXTERNAL &#xff1a;只检索最外面的轮廓&#xff1b;RETR_LIST&#xff1a;检索所有的轮廓&#xff0c;并将其保存到一条链表当中&#xff1b;RETR_CCOMP&#xff1a;检索所有的轮廓&#xff0c;并将他们组…

魔方网表 存在 mailupdate.jsp接口 任意文件上传漏洞

声明&#xff1a; 本文仅用于技术交流&#xff0c;请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任。 简介 魔方网表mailupdate.jsp接口存在任意文件上传漏洞 …

ChatGPT深度科研应用、数据分析及机器学习、AI绘图与高效论文撰写教程

原文链接&#xff1a;ChatGPT深度科研应用、数据分析及机器学习、AI绘图与高效论文撰写https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247601506&idx2&sn5dae3fdc3e188e81b8a6142c5ab8c994&chksmfa820c85cdf58593356482880998fc6eb98e6889b261bf621e1d…

python生成二维码

要在Python中生成二维码&#xff0c;可以使用第三方库qrcode。首先&#xff0c;确保已经安装了qrcode库&#xff1a; pip install qrcode然后&#xff0c;使用以下代码生成二维码&#xff1a; import qrcodedata "https://mp.csdn.net/mp_blog/creation/editor?spm100…

Kafka服务端(含Zookeeper)一键自启软件

1. 前言 本文介绍了一款集成图形化界面配置和一键自启功能的Kafka与Zookeeper服务管理软件。该软件通过直观易用的图形界面&#xff0c;使用户能够轻松完成Kafka和Zookeeper的配置工作&#xff0c;有效避免了手动编辑配置文件可能带来的错误和不便。同时&#xff0c;软件还提供…

【附gpt4.0升级秘笈】百度智能云万源全新一代智能计算操作系统发布:引领AI新纪元

在科技日新月异的今天&#xff0c;人工智能&#xff08;AI&#xff09;作为引领未来发展的关键技术&#xff0c;正逐步渗透到社会的每一个角落。百度&#xff0c;作为中国AI领域的领军企业&#xff0c;始终站在技术创新的前沿&#xff0c;不断推出引领行业的重磅产品。今日&…

论文略读:SWE-bench: Can Language Models Resolve Real-world Github Issues?

iclr 2024 oral reviewer评分 5668 现有的语言模型&#xff08;LMs&#xff09;的基准测试已经饱和&#xff0c;无法捕捉到最先进的语言模型能做什么和不能做什么的前沿。 ——>要具有挑战性的基准测试论文引入了SWE-bench 在现实软件工程环境中评估语言模型的基准测试 ​​…

使用 code-server 搭建在线的 VS Code 编辑器

文章目录 前言安装体验后记 前言 VS Code 是一个非常流行的代码编辑器&#xff0c;安装各种拓展下也可以当作全功能的IDE使用。VS Code本身是基于Web方案构建的&#xff0c;完全可以搭建服务器&#xff0c;然后通过浏览器访问。事实上官方就是这么设计的。现在打开任何一个Git…