前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >设计模式实战:原型模式实现场景对象的复制

设计模式实战:原型模式实现场景对象的复制

作者头像
你好戴先生
发布于 2021-09-23 07:49:56
发布于 2021-09-23 07:49:56
41700
代码可运行
举报
文章被收录于专栏:戴言泛滥戴言泛滥
运行总次数:0
代码可运行

传送门:【设计模式系列(三)】彻底搞懂原型模式

## 需求

1、 有一个程序,会有多个不同的用户并发访问

2、程序中包含多个场景,根据用户首次访问的输入内容匹配得到符合条件的场景

3、不同的场景需要对外提供统一的匹配和处理输入的接口,但处理逻辑和方法又各不相同

4、同一个用户存在多轮次访问的情况,并且场景会根据多轮访问的情况决定当前轮次的处理方法,要求每个用户要有一个独立的场景对象处理用户的输入内容

5、每个用户有一个独立的id标识

## 类图

1、定义一个场景抽象类,具体场景类继承抽象类,并实现初始化方法和处理输入方法

2、抽象类实现Cloneabel接口以实现原型模式,实现Serializable接口以实现对象的深度克隆

3、定义SceneMatchWord类,实现场景的匹配功能

4、定义SceneContext类用来存储场景实例对象,并提供匹配和获取场景的唯一接口方法

5、定义Main类,作为模拟程序的入口接口,通过控制台输入模拟用户输入

## 主要代码

### 场景抽象类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 场景超类
 * @author daijiyong
 */
abstract public class AbstractScene implements Cloneable, Serializable {
    /**
     * 场景名字
     */
    public SceneNameCode sceneNameCode;
    /**
     * 当前场景的匹配词
     */
    protected LinkedList<SceneMatchWord> matchWords;
    public AbstractScene() {
    }
    public AbstractScene(SceneNameCode sceneNameCode) {
        this.sceneNameCode = sceneNameCode;
    }
    /**
     * 对外统一处理操作,子类进行重写
     */
    public abstract String deal(String userInput);
    /**
     * 初始化操作,子类进行重写
     */
    protected abstract void init();
    /**
     * 根据用户输入与当前场景进行匹配
     *
     * @param userInput 用户输入内容
     * @return 匹配结果
     */
    public Boolean match(String userInput) {
        // TODO
        //  根据用户的输入进行匹配
        //  匹配成功则返回true,失败则返回false
        for (SceneMatchWord smw : matchWords) {
            if (smw.match(userInput)) {
                return true;
            }
        }
        return false;
    }
    /**
     * 深克隆
     *
     * @return 克隆结果
     */
    @Override
    public AbstractScene clone() {
        AbstractScene clone = null;
        try {
            clone = (AbstractScene) super.clone();
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bo);
            oos.writeObject(this);
            ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
            ObjectInputStream oi = new ObjectInputStream(bi);
            clone = (AbstractScene) oi.readObject();
        } catch (IOException | ClassNotFoundException | CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }
}

### 场景子类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class NumberReverseQueryScene extends AbstractScene {
    public NumberReverseQueryScene(SceneNameCode sceneNameCode) {
        super(sceneNameCode);
        init();
    }
    @Override
    public String deal(String userInput) {
        // TODO
        //  当前场景对用户输入的具体实现
        //  并返回结果
        return String.format("%s处理用户的输入内容%s\n", sceneNameCode.getName(), userInput);
    }
    /**
     * 初始化当前场景数据
     */
    @Override
    public void init() {
        // 初始化匹配内容
        matchWords = new LinkedList<>();
        //5个或5个以上数字,不含字母,非1非0开头号码
        matchWords.add(new SceneMatchWord(Pattern.compile("[2-9]\\d{4,}")));
        //5个或5个以上数字,不含字母,1开头号码
        matchWords.add(new SceneMatchWord(Pattern.compile("1\\d{4,}")));
    }
}

### 场景匹配规则类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 场景匹配词
 *
 * @author daijiyong
 */
public class SceneMatchWord implements Serializable {
    // 匹配规则
    private Pattern rule;
    /**
     * 根据用户输入内容进行匹配
     * 匹配成功返回true,失败返回false
     *
     * @param userInput 用户输入
     * @return 匹配成功或失败
     */
    public Boolean match(String userInput) {
        return matchRule(userInput);
    }
    private boolean matchRule(String str) {
        if (rule == null) {
            return false;
        }
        return rule.matcher(str).find();
    }
}

### 场景上下文类

初始化场景对象

调用场景的匹配方法,根据用户的输入为每一个用户创建一个特有的场景对象 并使用ConcurrentHashMap来存储不同用户的场景对象

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class SceneContext {
    private final static Map<String, AbstractScene> CONTEXT = new ConcurrentHashMap<>();
    private final static ArrayList<AbstractScene> SCENES = new ArrayList<>();
    static {
        // 初始化场景集合
        SCENES.add(SceneFactory.createNumberReverseQueryScene());
        SCENES.add(SceneFactory.createMoveCarScene());
        SCENES.add(SceneFactory.createAreaCodeReverseQueryScene());
    }
    public static AbstractScene currentScene(String queryId, String userInput) {
        if (getContext().get(queryId) == null && SCENES.size() > 0) {
            for (AbstractScene as : SCENES) {
                if (as.match(userInput)) {
                    CONTEXT.put(queryId, as.clone());
                    System.out.printf("用户%s匹配到场景:%s\n", queryId, as.sceneNameCode.getName());
                    return getContext().get(queryId);
                }
            }
        }
        return getContext().get(queryId);
    }
    public static Map<String, AbstractScene> getContext() {
        return CONTEXT;
    }
}

### 模拟程序入口类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*
   模拟入口程序
 */
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            // 输入两个内容,用户id和用户请求内容,中间用空格隔开
            String input = scanner.nextLine();
            String[] inputArr = input.split(" ");
            AbstractScene scene = SceneContext.currentScene(inputArr[0], inputArr[1]);
            System.out.println(scene.deal(inputArr[1]));
        }
    }
}

运行程序,可实现为每个用户创建独立的场景对象

点击阅读原文访问完整代码地址

包路径:com/dai/designpattern/prototype/practice

文/戴先生@2021年9月13日

---end---

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-09-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 你好戴先生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
2017值得一瞥的JavaScript相关技术趋势
跨年前两天,Dan Abramov在Twitter上提了一个问题: JS社区毫不犹豫的抛出了它们对于新技术的预期与期待,本文内容也是总结自Twitter的回复,按照流行度降序排列。有一个尚未确定的小
前朝楚水
2018/04/03
1.3K0
2017值得一瞥的JavaScript相关技术趋势
前端专家聊JS语言家族新成员——R&B
摘要 相信大家对以CoffeeScript、TypeScript为代表的编译到JavaScript的语言已经不陌生。本次分享将介绍 JS 平台语言家族的重要新成员R&B——Reason(Faceboo
IT大咖说
2018/04/04
1.5K0
TypeScript 是弱类型
以下这段代码不管是在 JavaScript 中还是在 TypeScript 中都是可以正常运行的,运行时数字 1 会被隐式类型转换为字符串 '1',加号 + 被识别为字符串拼接,所以打印出结果是字符串 '11'。
HoneyMoose
2021/11/16
6840
TypeScript 是弱类型
编程语言傻傻分不清:弱类型、强类型、动态类型、静态类型
这篇文章综合介绍了四种分类,特别地,为了方便大家快速有效的学习,笔者尝试用思维导图的办法描述编程语言的区别。一般来讲,看第一个图就够了。但如果你想更深入地了解,也可以参考下面的文字表述。
陈满iOS
2018/09/10
9.7K1
编程语言傻傻分不清:弱类型、强类型、动态类型、静态类型
【TypeScript】001-TypeScript 的概述
这种灵活性就像一把双刃剑,一方面使得 JavaScript 蓬勃发展,无所不能,从 2013 年开始就一直蝉联最普遍使用的编程语言排行榜冠军;另一方面也使得它的代码质量参差不齐,维护成本高,运行时错误多。
訾博ZiBo
2025/01/06
710
【TypeScript】001-TypeScript 的概述
下一代前端语言之争,JavaScript 要被新语言反超?
作者|Nicholas Yang 译者|核子可乐 策划|褚杏娟 假如大家正在编写前端代码,那么会选择哪种编程语言?目前来看,最有希望的选手主要有三个:首先是最常规的 JavaScript,然后是能编译为 WebAssembly(Wasm)的语言,最后则是能编译成 JavaScript 的语言。 常规 JavaScript 需要的配套工具最少,但代价是调试起来相当麻烦,代码可读性也差。虽然选择 JS 确实门槛较低,不过除了一味痴迷“极简主义”的铁粉以外,我个人觉得这个选项只能说一般。 能编译为 Wa
深度学习与Python
2023/03/29
4020
下一代前端语言之争,JavaScript 要被新语言反超?
谁告诉的你们Python是强类型语言!站出来,保证不打你!
最近有些学员问我,Python到底是强类型语言,还是弱类型语言。我就直接脱口而出:Python是弱类型语言。没想到有一些学员给我了一些文章,有中文的,有英文的,都说Python是强类型语言。我就很好奇,特意仔细研究了这些文章,例如,下面就是一篇老外写的文章:
蒙娜丽宁
2020/08/31
1.1K0
谁告诉的你们Python是强类型语言!站出来,保证不打你!
Go 数据类型篇(二):布尔类型、整型、浮点型和复数类型
与其他静态语言不同的是,Go 新增了一个通道类型,该类型主要用于并发编程时不同协程之间的通信,后面介绍 Go 语言并发编程的时候会详细介绍它。
学院君
2023/03/03
1.4K0
Go 数据类型篇(二):布尔类型、整型、浮点型和复数类型
编译型语言、解释型语言、静态类型语言、动态类型语言、强类型语言、弱类型语言概念与区别
编译型语言和解释型语言 1、编译型语言 需通过编译器(compiler)将源代码编译成机器码,之后才能执行的语言。一般需经过编译(compile)、链接(linker)这两个步骤。编译是把源代码编译成机器码,链接是把各个模块的机器码和依赖库串连起来生成可执行文件。 优点:编译器一般会有预编译的过程对代码进行优化。因为编译只做一次,运行时不需要编译,所以编译型语言的程序执行效率高。可以脱离语言环境独立运行。 缺点:编译之后如果需要修改就需要整个模块重新编译。编译的时候根据对应的运行环境生成机器码,不同的
Albert陈凯
2018/04/04
3.2K0
前端工程化发展历史
毕业前对前端工程化一直没有什么切身的体会,现在工作也有半年多了,体会也越来越深,npm,yarn,Webpack ,gulp,Babel,ESlint,TypeScript 最近准备一一去深入了解一下,看到一篇不错的关于前端工程化的发展过程,就翻译了一下,How it feels to learn JavaScript in 2016,
windliang
2022/09/23
7890
MoonBit:Wasm优化语言,代码量少于Rust
MoonBit 是一种端到端的编程语言,针对 WebAssembly 进行了优化,同时也可以编译成 JavaScript 和汇编代码。
云云众生s
2024/06/30
2080
强类型 JavaScript 的解决方案
JavaScript 是一种弱类型(或称动态类型)语言,即变量的类型是不确定的。 x = 5; // 5 x = x + 'A'; // '5A' 上面代码中,变量x起先是一个数值,后来是一个字符串,类型完全由当前的值决定,这就叫弱类型。 弱类型的好处是十分灵活,可以写出非常简洁的代码。但是,对于大型项目来说,强类型更有利,可以降低系统的复杂度,在编译时就发现类型错误,减轻程序员的负担。 一直有人尝试,让 JavaScript 变成强类型语言。在官方最终支持强类型之前,本文介绍三种现在就可
ruanyf
2018/04/12
9770
强类型 JavaScript 的解决方案
【Python】Python中的数据类型
在上一篇内容中我们介绍了Python中的常量与变量的相关内容。常量也就是不可改变的量,与之对应的变量则是可以改变的量。
蒙奇D索隆
2024/09/07
810
【Python】Python中的数据类型
Java Grammar:数据类型
我们知道,Java是一种 强类型 语言,类型对于Java语言来说非常的重要不言而喻,在Java中,分为 基础数据类型 和 引用数据类型 ,其中基础数据类型分为了 四类八种:
山禾说
2019/08/08
5890
Java Grammar:数据类型
Go 数据类型篇(四):基本数据类型之间的转化
通过前面两篇教程,学院君已经介绍完了 Go 语言中的基本数据类型,分别是布尔类型、整型、浮点型、复数类型、字符串和字符类型,此外,Go 语言还支持这些基本数据类型之间的转化,不过由于 Go 是强类型语言,所以不支持动态语言那种自动转化,而是要对变量进行强制类型转化。
学院君
2023/03/03
5600
Go 数据类型篇(四):基本数据类型之间的转化
编程语言的弱类型、强类型、动态类型、静态类型的解释
例如在SQL语言中,当一个整数与一个浮点数相加时,系统会自动将整数转换为浮点数,以便进行运算并得到正确的结果;或者对int类型列 输入一个字符串类型,如果系统发现该字符串可以转化成int类型数字,则会将其自动转化成int类型数字
黎鹤舞
2024/03/19
7100
编程语言的弱类型、强类型、动态类型、静态类型的解释
PHP数据类型转换
        Java,c,c++等强类型语言必须先声明数据类型,java和c声明一个整数型(int a=100;)
十月梦想
2018/08/29
1.7K0
Go 语言基础入门教程 —— 数据类型篇:概述和布尔类型
相较于 PHP,多出了字符类型(单个字符)、错误类型和复数类型,PHP 通过系统级配置函数 error_reporting 定义应用的错误报告级别,不区分单独的字符与字符串类型,Go 还对整型的精度及是否有符号(正数还是负数)做了区分,PHP 则只有一个 int 类型标识整型数据,另外 PHP 通过 float 和 double 来区分浮点型精度,这一点也是 Go 语言 和 PHP 不一样的地方。
学院君
2019/08/08
5460
【Java SE语法篇】2.数据类型和变量
其中,“Hello world!”,100,3.14,‘A’,true/false都是常量,将其称为字面常量。
爱敲代码的小杨.
2024/05/07
810
【Java SE语法篇】2.数据类型和变量
《JavaSE-第二章》之基本数据类型与类型转换
java语言有三种输出方式,第一种是打印不换行,第二种是打印并换行,第三种是格式化输出。
用户10517932
2023/10/07
2090
《JavaSE-第二章》之基本数据类型与类型转换
推荐阅读
相关推荐
2017值得一瞥的JavaScript相关技术趋势
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验