Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
设计模式---原型模式
原型模式(Prototype Pattern):使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式是一种对象创建型模式。
大忽悠爱学习
2021/11/15
4050
『设计模式』设计模式--原型模式
原型模式(Prototype Pattern)是通过给出一个原型对象来指明所要创建的对象类型,然后用复制这个原型对象的办法创建出更多的同类对象,同时又能保证性能而且不需要知道内部细节。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
风骨散人Chiam
2020/10/28
1.2K0
设计模式——原型模式
设计模式中,单例模式应该是大家最为熟悉的了,那如果我们需要对一个对象进行多次复制的话,大家会用什么呢?这就要用到今天要讲的原型模式了。
健程之道
2019/11/02
4170
设计模式【5】-- 原型模式
设计模式文章集合:http://aphysia.cn/categories/designpattern
秦怀杂货店
2021/12/11
4030
设计模式之原型模式
创建型模式之原型模式 定义 原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式是实现了一
爱撒谎的男孩
2018/05/25
4240
设计模式之原型模式(Prototype)
我们知道,一个类的定义中包括属性和方法。属性用于表示对象的状态,方法用于表示对象所具有的行为。其中,属性既可以是Java中基本数据类型,也可以是引用类型。Java中的浅复制通常使用clone()方式完成。
用户1205080
2018/12/05
3270
【设计模式系列(三)】彻底搞懂原型模式
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能
你好戴先生
2020/09/01
5650
020.原型模式
我们今天来考虑一下给用户邮箱发广告信这个模块是怎么开发的。既然是广告信,肯定需要一个模版,然后再从数据库中把客户的信息一个一个的取出,放到模版中生成一份完整的邮件,然后扔给发送机进行发送处理,我们来看类图:
CoderJed
2021/01/13
2200
设计模式 | 原型模式及典型应用
原型模式(Prototype Pattern):使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式是一种对象创建型模式。
小旋锋
2019/01/21
3510
设计模式(十一):原型模式
我们都看过《西游记》,里面孙悟空拥有拔毛变分身的技能,只需要拔毛轻轻一吹就会变出许许多多的孙悟空。孙悟空本体就是原型实例,通过分身术复制变出新的孙悟空,分身孙悟空与本体孙悟空相对独立,即分身孙悟空遇到任何问题,都不会影响本体孙悟空。原型模式正是采用这种思想,用一个已经创建成功的对象实例作为原型,通过复制该原型实例来创建一个和原型实例相同或相似的新对象。
xujjj
2019/07/31
4030
设计模式(十一):原型模式
设计模式—— 十三 :原型模式
原型模式的核心是一个clone方法,通过该方法进行对象的拷贝,Java 提供了一个Cloneable接口来标示这个对象是可拷贝的,Cloneable接口的作用是标记,在JVM中具有这个标记的对象才有可能被拷贝。那怎么才能从“有可能被拷贝”转换为“可以被拷贝”呢?方法是覆盖 clone()方法:
三分恶
2020/07/16
5700
23种设计模式之原型模式
在有些系统中,存在大量相同或相似对象的创建问题,如果用传统的构造函数来创建对象,会比较复杂且耗时耗资源,用原型模式生成对象就很高效,就像孙悟空拔下猴毛轻轻一吹就变出很多孙悟空一样简单。
Java技术债务
2022/09/26
2080
23种设计模式之原型模式
大牧絮叨设计模式:原型模式
原型模式(Prototype)[GOF95]是一种对象的创建模式,通过给定一个参考的原型对象来指定要创建的对象的类型及数据,然后复制该对象创建更多的相同对象的方式完成对象的构建过程。
大牧莫邪
2019/07/23
3730
大牧絮叨设计模式:原型模式
原型模式
原型模式的简单程度仅次于单例模式,核心方法就一个clone(),在java中只需要实现接口Cloneable即可 原型模式通过把对象复制(clone)一遍,产生一个新的对象,和原有对象一样,然后再修改
张俊怡
2018/04/24
5240
原型模式
一起学习设计模式--05.原型模式
《西游记》中的孙悟空吹猴毛变出很多猴兵的故事想必大家都知道,《火影》中鸣人的多重影分身大部分人应该也是都知道,他们都可以根据自己的形象,复制(又称克隆)出很多和自己一摸一样的“身外身”来。在设计模式中也存在一个类似的模式,可以通过一个原型对象克隆出多个一模一样的对象,该模式被成为原型模式。
独立观察员
2022/12/06
3040
一起学习设计模式--05.原型模式
四、原型模式与建造者模式详解
原型模式(PrototypePattern)是指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象,属于创建型模式。
编程之心
2020/08/12
5900
四、原型模式与建造者模式详解
设计模式入门:原型模式
  实际应用中,原型模式可以简单理解为克隆操作。在大多数面向对象编程语言中,实现克隆操作并不复杂,对于Java,我们只需继承Cloneable接口,并重写Object的clone()即可(非必须)。
happyJared
2018/09/20
2440
设计模式入门:原型模式
Java设计模式之原型模式
现在有一只羊,姓名为:tom,年龄为:1,颜色为:白色,请编写程序创建和tom羊属性完全相同的10只羊。
shaoshaossm
2022/12/27
2190
Java设计模式学习笔记—原型模式
文章最后“Java设计模式笔记示例代码整合”为本系列代码整合,所有代码均为个人手打并运行测试,不定期更新。本节内容位于其Prototype包(package)中。
WindCoder
2018/09/20
3800
Java设计模式学习笔记—原型模式
设计模式-原型模式
关于Cloneable 接口,用途和Serializable一样为标记型接口,内部没有方法和属性,implements Cloneable 表示对象能被克隆,即能使用Object.clone()方法,
mySoul
2018/12/02
4960
相关推荐
设计模式---原型模式
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验