设计模式08-行为型模式1(命令模式/迭代器模式/观察者模式/Java)

五、行为型模式

  • **行为模式的定义:**行为型模式是对不同的对象之间划分职责和算法的抽象化。行为型模式定义了系统中对象之间的交互与通信,研究系统在运行时对象之间的相互通信与协作,进一步明确对象的职责,包括对系统中较为复杂的流程的控制。

  • 行为模式的分类:

    类行为型模式:使用继承关系在几个类之间分配行为,主要通过多态等方式来分配父类与子类的职责;

    对象行为型模式:使用对象的聚合关联关系来分配行为,主要通过对象关联等方式来分配两个或多个类的职责。

5.1 命令模式

5.1.1 命令模式的定义

描述对象之间的调用关系

**1.模式动机:**将请求发送者和接收者完全解耦;发送者与接收者之间没有直接引用关系;发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求

**2.模式定义:**将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。

5.1.2 命令模式的结构与分析

image-20241031200821297

//调用者
public class Invoker {private AbstractCommand ac;public Invoker(AbstractCommand ac) {this.ac = ac;}public void send() {ac.execute();}
}
//接收者
public class Receiver {public void action() {}
}
//抽象命令类
public abstract class AbstractCommand {public abstract void execute();
}
//具体命令类
public class ConcreteCommand extends AbstractCommand {private Receiver receiver = new Receiver();@Overridepublic void execute() {receiver.action();}
}
  • 命令模式的本质是对请求进行封装,一个请求对应于一个命令,将发出命令的责任和执行命令的责任分开

  • 将请求发送者和接收者完全解耦,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求如何被接收、操作是否被执行、何时被执行,以及是怎么被执行的。

5.1.3 命令模式的案例

电视机是请求的接收者,遥控器是请求的发送者,遥控器上有一些按钮,不同的按钮对应电视机的不同操作。抽象命令角色由一个命令接口来扮演,有三个具体的命令类实现了抽象命令接口,这三个具体命令类分别代表三种操作:打开电视机、关闭电视机和切换频道。显然,电视机遥控器就是一个典型的命令模式应用实例。

image-20241031203956626

public class TV {public void open() {System.out.println("打开电视");}public void change() {System.out.println("切换频道");}public void close() {System.out.println("关掉电视");}
}public interface Command {public void execute();
}public class OpenCommand implements Command{private TV tv = new TV();@Overridepublic void execute() {tv.open();}
}public class CloseCommand implements Command{private TV tv = new TV();@Overridepublic void execute() {tv.close();}
}public class ChangeCommand implements Command {private TV tv = new TV();@Overridepublic void execute() {tv.change();}
}public class Control {private Command openCommand;private Command changeCommand;private Command closeCommand;public Control(Command openCommand, Command changeCommand, Command closeCommand) {this.openCommand = openCommand;this.changeCommand = changeCommand;this.closeCommand = closeCommand;}public void open() {openCommand.execute();}public void change() {changeCommand.execute();}public void close() {closeCommand.execute();}
}public class Main {public static void main(String[] args) {Command openCommand = new OpenCommand();Command changeCommandCommand = new ChangeCommand();Command closeCommand = new CloseCommand();Control control = new Control(openCommand, changeCommandCommand, closeCommand);control.open();control.change();control.close();}
}
5.1.4 命令模式的优缺点
优点缺点
1.将系统的请求调用者和请求接收者解耦1.使用命令模式可能会导致某些系统有过多的具体命令类
2.添加命令符合开闭原则
3.可以比较容易地设计一个命令队列或宏命令(组合模式)
4.为请求的撤销(Undo)和恢复(Redo)操作提供了一种设计和实现方案
5.1.5 命令模式的适用场景
  • 需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互

  • 需要在不同的时间指定请求、将请求排队和执行请求

  • 需要支持命令的撤销(Undo)操作和恢复(Redo)操作

  • 需要将一组操作组合在一起形成宏命令

5.2 迭代器模式

5.2.1 迭代器模式的定义

1.模式动机:如何访问一个聚合对象(用于存储多个对象)中的元素但又不需要暴露它的内部结构,还能提供多种不同的遍历方式

2.模式定义:提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示。

5.2.2 迭代器模式的结构与分析

image-20241102214037189

  • 聚合对象的两个职责:存储数据,聚合对象的基本职责;遍历数据,既是可变化的,又是可分离的

  • 将遍历数据的行为从聚合对象中分离出来,封装在迭代器对象中,由迭代器来提供遍历聚合对象内部数据的行为,简化聚合对象的设计,更符合单一职责原则

  • 迭代器对象使用了工厂模式的设计思想,聚合类可以看作工厂模式,迭代器是产品类

实现方法一:由于集合和数组在聚合类中,迭代器需要使用它们,因此迭代器作为内部类出现

public interface Iterator {public void first();public void next();public boolean isLast();public Object currentItem();
}public abstract class Aggregate {public abstract Iterator createIterator();
}public class ConcreteAggregate extends Aggregate{private String[] strings;public ConcreteAggregate() {strings = new String[]{"d", "e", "f"};}@Overridepublic Iterator createIterator() {return new ConcreteIterator();}private class ConcreteIterator implements Iterator{private int index = 0;@Overridepublic void first() {index = 0;}@Overridepublic void next() {if (strings.length > index) {index++;} else {throw new RuntimeException("越界");}}@Overridepublic boolean isLast() {return index == strings.length;}@Overridepublic Object currentItem() {return strings[index];}}
}

实现方法二:可以在聚合类创建迭代器时,将自身传给迭代器并提供集合/数组的get方法,这样也可以实现

public interface Iterator {public void first();public void next();public boolean isLast();public Object currentItem();
}public abstract class Aggregate {public abstract Iterator createIterator();
}public class ConcreteAggregate extends Aggregate{private String[] strings;public ConcreteAggregate() {strings = new String[]{"a", "b", "c"};}public String[] getStrings() {return strings;}@Overridepublic Iterator createIterator() {return new ConcreteIterator(this);}
}public class ConcreteIterator implements Iterator{private ConcreteAggregate aggregate;private int index = 0;public ConcreteIterator(ConcreteAggregate aggregate) {this.aggregate = aggregate;}@Overridepublic void first() {index = 0;}@Overridepublic void next() {if (aggregate.getStrings().length > index) {index++;} else {throw new RuntimeException("越界");}}@Overridepublic boolean isLast() {return index == aggregate.getStrings().length;}@Overridepublic Object currentItem() {return aggregate.getStrings()[index];}
}public class Main {public static void main(String[] args) {Aggregate concreteAggregate = new ConcreteAggregate();Iterator iterator = concreteAggregate.createIterator();while (!iterator.isLast()) {System.out.println(iterator.currentItem());iterator.next();}}
}
5.2.3 迭代器模式的案例

电视机遥控器就是一个迭代器的实例,通过它可以实现对电视机频道集合的遍历操作,本实例我们将模拟电视机遥控器的实现。

image-20241102215617007

  • 迭代器类
public interface TVIterator {public void setChannel(int i);public Object currentChannel();public void next();public void previous();public boolean isLast();public boolean isFirst();
}public class SkyworthIterator implements TVIterator {private SkyworthTelevision skyworthTelevision;private int index = 0;public SkyworthIterator(SkyworthTelevision skyworthTelevision) {this.skyworthTelevision = skyworthTelevision;}@Overridepublic void setChannel(int i) {this.index = i;}@Overridepublic Object currentChannel() {return skyworthTelevision.getObj()[this.index];}@Overridepublic void next() {if (this.index < skyworthTelevision.getObj().length) {this.index++;}}@Overridepublic void previous() {if (this.index > 0) {this.index--;}}@Overridepublic boolean isLast() {return this.index == skyworthTelevision.getObj().length ;}@Overridepublic boolean isFirst() {return this.index == 0;}
}public class TCLIterator implements TVIterator{private TCLTelevision tclTelevision;private int index = 0;public TCLIterator(TCLTelevision tclTelevision) {this.tclTelevision = tclTelevision;}@Overridepublic void setChannel(int i) {this.index = i;}@Overridepublic Object currentChannel() {return tclTelevision.getObj()[this.index];}@Overridepublic void next() {if (this.index < tclTelevision.getObj().length) {this.index++;}}@Overridepublic void previous() {if (this.index > 0) {this.index--;}}@Overridepublic boolean isLast() {return this.index == tclTelevision.getObj().length;}@Overridepublic boolean isFirst() {return this.index == 0;}
}
  • 电视类
public interface Television {public TVIterator createIterator();public Object[] getObj();
}public class SkyworthTelevision implements Television{private Object[] obj = {"CCTV-1","CCTV-2","CCTV-3","CCTV-4","CCTV-5","CCTV-6","CCTV-7","CCTV-8"};@Overridepublic TVIterator createIterator() {return new SkyworthIterator(this);}@Overridepublic Object[] getObj() {return obj;}
}public class TCLTelevision implements Television{private Object[] obj = {"CCTV-1","CCTV-2","CCTV-3","CCTV-4","CCTV-5","CCTV-6","CCTV-7","CCTV-8"};@Overridepublic TVIterator createIterator() {return new TCLIterator(this);}@Overridepublic Object[] getObj() {return obj;}
}
  • 客户端
import org.w3c.dom.Document;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;public class XMLUtil {public static Object getBean() {try {//获取XMLDocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder db = dbf.newDocumentBuilder();Document parse = db.parse(new File("src/main/java/com/tyut/text3/example1/tv.xml"));String tv = parse.getElementsByTagName("tv").item(0).getFirstChild().getNodeValue();//获取对象Class<?> aClass = Class.forName(tv);return aClass.newInstance();} catch (Exception e) {return new RuntimeException(e);}}
}<?xml version="1.0" encoding="UTF-8" ?>
<tv>com.tyut.text3.example1.TCLTelevision</tv>public class Main {public static void main(String[] args) {TCLTelevision bean = (TCLTelevision) XMLUtil.getBean();TVIterator iterator = bean.createIterator();//正序遍历System.out.println("正序播放电视节目:");while (!iterator.isLast()) {System.out.println(iterator.currentChannel());iterator.next();}//倒序遍历System.out.println("倒序播放电视节目:");iterator.setChannel(8);while (!iterator.isFirst()) {iterator.previous();System.out.println(iterator.currentChannel());}}
}
  • 如果需要增加一个新的具体聚合类,只需增加一个新的聚合子类和一个新的具体迭代器类即可,原有类库代码无须修改,符合开闭原则

  • 如果需要更换一个迭代器,只需要增加一个新的具体迭代器类作为抽象迭代器类的子类,重新实现遍历方法即可,原有迭代器代码无须修改,也符合开闭原则

5.2.4 迭代器模式的优缺点
优点缺点
1.支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式,并且可以对同一个聚合对象同时多次遍历1.类的个数成对增加,这在一定程度上增加了系统的复杂性
2.简化了聚合类,符合单一职责原则
3.易扩展,符合开闭原则
5.2.5 迭代器模式的适用场景
  • 访问一个聚合对象的内容而无须暴露它的内部表示

  • 需要为一个聚合对象提供多种遍历方式

  • 为遍历不同的聚合结构提供一个统一的接口,在该接口的实现类中为不同的聚合结构提供不同的遍历方式,而客户端可以一致性地操作该接口

5.3 观察者模式

5.3.1 观察者模式的定义

描述对象之间的依赖关系

1.模式动机:一个对象的状态或行为的变化将导致其他对象的状态或行为也发生改变。定义了对象之间一种一对多的依赖关系,让一个对象的改变能够影响其他对象,发生改变的对象称为观察目标,被通知的对象称为观察者。

2.模式定义:定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。

5.3.2 观察者模式的结构与分析

image-20241103100453988

image-20241103100725809

  • 有时候在具体观察者类ConcreteObserver中需要使用到具体目标类ConcreteSubject中的状态(属性),会存在关联或依赖关系

  • 如果在具体层之间具有关联关系,系统的扩展性将受到一定的影响,增加新的具体目标类有时候需要修改原有观察者的代码,在一定程度上违背了开闭原则,但是如果原有观察者类无须关联新增的具体目标,则系统扩展性不受影响

//观察者
public interface Observer {public void update();
}
public class ConcreteObserver implements Observer{@Overridepublic void update() {System.out.println("更新操作");}
}
//目标
public abstract class Subject {protected ArrayList<Observer> arrayList = new ArrayList<>();public void attach(Observer observer) {arrayList.add(observer);}public void detach(Observer observer) {arrayList.remove(observer);}public abstract void notice();
}
public class ConcreteSubject extends Subject{@Overridepublic void notice() {for (Observer observer : arrayList) {observer.update();}}
}
public class Main {public static void main(String[] args) {Observer concreteObserver1 = new ConcreteObserver();Observer concreteObserver2 = new ConcreteObserver();ConcreteSubject concreteSubject = new ConcreteSubject();concreteSubject.attach(concreteObserver1);concreteSubject.attach(concreteObserver2);concreteSubject.notice();}
}
5.3.3 观察者模式的案例

在某多人联机对战游戏中,多个玩家可以加入同一战队组成联盟,当战队中的某一成员受到敌人攻击时将给所有其他盟友发送通知,盟友收到通知后将做出响应。

image-20241103105850293

public abstract class Observer {private String name;private int state;public Observer(String name) {this.name = name;this.state = 0;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getState() {return state;}public void setState(int state) {this.state = state;}public abstract void help();public abstract void hurt(AbstractTeam team);
}
public class Player extends Observer{public Player(String name) {super(name);}@Overridepublic void help() {if (getState() == 0) System.out.println(getName() + "帮助受伤的队友");}@Overridepublic void hurt(AbstractTeam team) {setState(1);System.out.println(getName() + "受伤了呼叫" + team.getTeamName() + "队友的帮忙");team.notice();}
}
public abstract class AbstractTeam {private String teamName;protected ArrayList<Observer> observers = new ArrayList<>();public void add(Observer observer) {observers.add(observer);}public void remove(Observer observer) {observers.remove(observer);}public String getTeamName() {return teamName;}public void setTeamName(String teamName) {this.teamName = teamName;}public abstract void notice();
}
public class Team extends AbstractTeam {@Overridepublic void notice() {for (Observer observer : observers) {observer.help();}}
}
public class Main {public static void main(String[] args) {AbstractTeam team = new Team();team.setTeamName("战狼队");Player player1 = new Player("张三");Player player2 = new Player("李四");Player player3 = new Player("王五");Player player4 = new Player("赵六");team.add(player1);team.add(player2);team.add(player3);team.add(player4);player1.hurt(team);}
}
5.3.4 观察者模式的优缺点
优点缺点
1.可以实现表示层和数据逻辑层的分离1.将所有的观察者都通知到会花费很多时间
2.在观察目标和观察者之间建立一个抽象的耦合,符合开闭原则,增加新的具体观察者无须修改原有系统代码2.如果存在循环依赖时可能导致系统崩溃
3.ü支持广播通信,简化了一对多系统设计的难度3.没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而只是知道观察目标发生了变化
5.3.5 观察者模式的适用场景
  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两个方面封装在独立的对象中使它们可以各自独立地改变和复用

  • 一个对象的改变将导致一个或多个其他对象发生改变,且并不知道具体有多少对象将发生改变,也不知道这些对象是谁

  • 需要在系统中创建一个触发链,A对象影响B对象,B对象影响C对象。

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

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

相关文章

服务器作业2

关闭防火墙 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 配置文件 创建用户nfs-upload [rootlocalhost ~]# useradd -u 210 nfs-upload [rootlocalhost ~]# groupmod -g 210 nfs-upload 创建tom用户 [rootlocalhost ~]# useradd tom 查看to…

【数据结构】堆:建堆/向下调整/上向调整/堆排序/TOK问题

文章目录 前言堆的定义1.大小堆2.完全二叉树 堆的实现堆的数据结构初始化销毁取堆顶元素判断堆是否为空父结点和子结点下标关系&#xff08;重要&#xff09; 向下调整法-O(n)小堆版大堆版 向上调整法-nlog(n)堆的插入和删除插入(调用向上调整)删除(调用向下调整) 构建最大堆向…

java学习1

一、运算符 1.算术运算符 在代码中&#xff0c;如果有小数参与计算&#xff0c;结果有可能不精确 1-1.隐式转换和强制转换 数字进行运算时&#xff0c;数据类型不一样不能运算&#xff0c;需要转成一样的&#xff0c;才能运算 &#xff08;1&#xff09;隐式转换&#xff1a…

20.体育馆使用预约系统(基于springboot和vue的Java项目)

目录 1.系统的受众说明 2.开发环境与技术 2.1 Java语言 2.2 MYSQL数据库 2.3 IDEA开发工具 2.4 Spring Boot框架 3.需求分析 3.1 可行性分析 3.1.1 技术可行性 3.1.2 经济可行性 3.1.3 操作可行性 3.2 系统流程分析 3.3 系统性能需求 3.4 系统功能需求 4.系…

Halcon3D image_points_to_world_plane详解

分三个部分来聊聊这个算子 一,算子的参数介绍 二,算法的计算过程 三,举例实现 第一部分,算子的介绍 image_points_to_world_plane( : : CameraParam, WorldPose, Rows, Cols, Scale : X, Y) 参数介绍: CameraParam,:相机内参 WorldPose 世界坐标系,也叫物体坐标系(成…

【启程Golang之旅】并发编程构建简易聊天系统

欢迎来到Golang的世界&#xff01;在当今快节奏的软件开发领域&#xff0c;选择一种高效、简洁的编程语言至关重要。而在这方面&#xff0c;Golang&#xff08;又称Go&#xff09;无疑是一个备受瞩目的选择。在本文中&#xff0c;带领您探索Golang的世界&#xff0c;一步步地了…

无人机场景 - 目标检测数据集 - 夜间车辆检测数据集下载「包含VOC、COCO、YOLO三种格式」

数据集介绍&#xff1a;无人机场景夜间车辆检测数据集&#xff0c;真实场景高质量图片数据&#xff0c;涉及场景丰富&#xff0c;比如夜间无人机场景城市道路行驶车辆图片、夜间无人机场景城市道边停车车辆图片、夜间无人机场景停车场车辆图片、夜间无人机场景小区车辆图片、夜…

HTML学习笔记十

系列笔记目录 第一章 HTML的概述 第二章 URL简介 第三章 网页元素的属性 第四章 html字符编码 第五章 网页的语义结构 第六章 文本标签 第七章 列表标签 第八章 图像标签 第九章 链接标签 第十章 多媒体标签 多媒体标签 系列笔记目录前言一、简介二、常用标签2.1<video>2…

Thumb 汇编指令集,Thumb 指令编码方式,编译 Thumb 汇编代码

版权归作者所有&#xff0c;如有转发&#xff0c;请注明文章出处&#xff1a;https://cyrus-studio.github.io/blog/ Thumb指令集 ARM 指令集&#xff1a;最早在 1985 年随第一代 ARM 处理器问世。ARM 指令集一开始是 32 位固定长度的指令&#xff0c;用于各种计算任务。 Thu…

【Clikhouse 探秘】ClickHouse 物化视图:加速大数据分析的新利器

&#x1f449;博主介绍&#xff1a; 博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家&#xff0c;WEB架构师&#xff0c;阿里云专家博主&#xff0c;华为云云享专家&#xff0c;51CTO 专家博主 ⛪️ 个人社区&#x…

【HarmonyOS NEXT】在 HarmonyOS NEXT 中实现优雅的加载动画

【HarmonyOS NEXT】在 HarmonyOS NEXT 中实现优雅的加载动画 在移动应用开发中&#xff0c;加载动画是提升用户体验的重要工具。在应用程序处理数据或加载页面时&#xff0c;为用户提供视觉反馈尤为关键。在这篇博客中&#xff0c;我们将探讨如何在 HarmonyOS NEXT 中使用 Sta…

Redis高级篇之缓存一致性详细教程

文章目录 0 前言1.缓存双写一致性的理解1.1 缓存按照操作来分 2. 数据库和缓存一致性的几种更新策略2.1 可以停机的情况2.2 我们讨论4种更新策略2.3 解决方案 总结 0 前言 缓存一致性问题在工作中绝对没办法回避的问题&#xff0c;比如&#xff1a;在实际开发过程中&#xff0c…

C++_day2

目录 1. 引用 reference&#xff08;重点&#xff09; 1.1 基础使用 1.2 特性 1.3 引用参数 2. C窄化&#xff08;了解&#xff09; 3. 输入&#xff08;熟悉&#xff09; 4. string 字符串类&#xff08;掌握&#xff09; 4.1 基础使用 4.2 取出元素 4.3 字符串与数字转换 5. …

Vuex的基本使用

文章目录 一、Vuex概述1.是什么2.使用场景3.优势4.注意二、如何构建vuex多组件共享数据环境1.创建项目2.创建三个组件3.源代码三、vuex 的使用 - 创建仓库1.安装 vuex2.新建 `store/index.js` 专门存放 vuex3.创建仓库 `store/index.js`4 在 main.js 中导入挂载到 Vue 实例上5.…

WPF+MVVM案例实战(二十一)- 制作一个侧边弹窗栏(CD类)

文章目录 1、案例效果1、侧边栏分类2、CD类侧边弹窗实现1、样式代码实现2、功能代码实现3 运行效果4、源代码获取1、案例效果 1、侧边栏分类 A类 :左侧弹出侧边栏B类 :右侧弹出侧边栏C类 :顶部弹出侧边栏D类 :底部弹出侧边栏2、CD类侧边弹窗实现 1、样式代码实现 在原有的…

揭开广告引擎的神秘面纱:如何在0.1秒内精准匹配用户需求?

目录 一、广告系统与广告引擎介绍 &#xff08;一&#xff09;广告系统与广告粗分 &#xff08;二&#xff09;广告引擎在广告系统中的重要性分析 二、广告引擎整体架构和工作过程 &#xff08;一&#xff09;一般概述 &#xff08;二&#xff09;核心功能架构图 三、标…

[论文阅读]A Survey of Embodied Learning for Object-Centric Robotic Manipulation

Abstract --以对象为中心的机器人操纵的Embodied learning是体现人工智能中一个快速发展且具有挑战性的领域。它对于推进下一代智能机器人至关重要&#xff0c;最近引起了人们的极大兴趣。与数据驱动的机器学习方法不同&#xff0c;具身学习侧重于通过与环境的物理交互和感知反…

NFTScan Site:以蓝标认证与高级项目管理功能赋能 NFT 项目

自 NFTScan Site 上线以来&#xff0c;它迅速成为 NFT 市场中的一支重要力量&#xff0c;凭借对各类 NFT 集合、市场以及 NFTfi 项目的认证获得了广泛认可。这个平台帮助许多项目提升了曝光度和可见性&#xff0c;为它们在竞争激烈的 NFT 市场中创造了更大的成功机会。 在最新更…

指数分布的原理和应用

本文介绍指数分布&#xff0c;及其推导原理。 Ref: 指数分布 开始之前&#xff0c;先看个概率密度函数的小问题&#xff1a; 问题描述&#xff1a;你于上午10点到达车站&#xff0c;车在10点到10:30 之间到达的时刻 X 的概率密度函数如图&#xff1a; 则使用分段积分&#xff0…

Javase——正则表达式

正则表达式的相关使用 public static void main(String[] args) {//校验QQ号 System.out.println("3602222222".matches("[1-9][0-9]{4,}"));// 校验18位身份证号 System.out.println("11050220240830901X".matches("^([0-9]){7,18}…