1、原型模式应用场景

  当遇到大量耗费劳动力的 get,set赋值场景时,如下:

public class SetGetParam {
public void setParam(UserDto userDto) {
User user = new User();
user.setAge(userDto.getAge());
//...
     userDao.addUser(user);
}
}

  原型模式(Prototype pattern)是指原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。原型模式主要适用于以下:

  (1)类初始化消耗资源较多;

  (2)使用new 生成一个对象需要非常繁琐的过程(数据准备访问权限等);

  (3)构造函数比较复杂;

  (4)在循环体中产生大量对象;

  在spring中用到的原型模式有:scope="prototype" ,还有常用的JSON.parseObject()也是一种原型模式

2、浅克隆

  创建具体需要克隆的类:

@Data
public class User {
private String name; private Integer age; private List<String> hobbies; public UserDto clone() {
UserDto dto = new UserDto();
dto.setAge(this.age);
dto.setName(this.name);
dto.setHobbies(this.hobbies);
return dto;
}
}

  创建Client:

public class Client {
private User user; public Client(User user) {
this.user = user;
} public UserDto startClone(User user) {
return user.clone();
}
}

  测试克隆,对比复制过来的值是否有自己的地址,还是用的原来的地址

public class PrototypeTest {
public static void main(String[] args) {
//创建具体需要克隆的对象
User user = new User();
user.setName("皮肤黝黑的小白");
user.setHobbies(new ArrayList<>());
System.out.println(user);
//创建Client对象,准备开始克隆
Client client = new Client(user);
UserDto dto = client.startClone(user);
System.out.println(dto);
System.out.println(user.getHobbies() == dto.getHobbies());
System.out.println(user.getName() == dto.getName());
}
}

  结果:

User(name=皮肤黝黑的小白, age=null, hobbies=[])
UserDto(name=皮肤黝黑的小白, age=null, hobbies=[])
true
true

  从测试结果可以看出:hobbies和name的内存地址是相同的,这说明我们并没有重新创建对象,这就是浅克隆。

3、深克隆

  采用序列化反序列化克隆,实现深克隆,

@Data
public class UserDeepClone implements Cloneable {
private String name; private Integer age; private List<String> hobbies; @Override
protected Object clone() throws CloneNotSupportedException {
return this.deepClone();
} public UserDto deepClone() {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
UserDto dto = (UserDto) ois.readObject();
return dto;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
public class DeepCloneTest {
public static void main(String[] args) {
DeepCloneTest deepCloneTest = new DeepCloneTest();
UserDeepClone user = new UserDeepClone();
user.setName("皮肤黝黑的小白");
user.setHobbies(new ArrayList<>());
System.out.println(user);
UserDto dto = null;
try {
dto = (UserDto) deepCloneTest.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println(dto);
System.out.println(user.getName() == dto.getName());
System.out.println(user.getHobbies() == dto.getHobbies());
}
}

4、克隆破坏单例

  深克隆会破坏单例,其实防御方式很简单,单例类不要实现Cloneable接口即可。

5、ArrayList中clone()方法的源码

    public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}

  

  

Spring中常见的设计模式——原型模式的更多相关文章

  1. Spring中常见的设计模式——代理模式

    一.代理模式的应用场景 生活中的中介,黄牛,等一系列帮助甲方做事的行为,都是代理模式的体现.代理模式(Proxy Pattern)是指为题对象提供一种代理,以控制对这个对象的访问.代理对象在客户端和目 ...

  2. Spring中常见的设计模式——策略模式

    策略模式(Strategy Pattern) 一.策略模式的应用场景 策略模式的应用场景如下: 系统中有很多类,而他们的区别仅仅在于行为不同. 一个系统需要动态的在集中算法中选择一种 二.用策略模式实 ...

  3. Spring中常见的设计模式——委派模式

    一.委派模式的定义及应用场景 委派模式(Delegate Pattern)的基本作用是负责任务的调用和分配,跟代理模式很像,可以看做特殊情况下的静态的全权代理,但是代理模式注重过程,而委派模式注重结果 ...

  4. Spring中常见的设计模式——工厂模式

    一.简单工厂模式 简单工厂模式(Simple Factory Pattern)由一个工厂对象决定创建哪一种产品类的实例,简单工厂模式适用于工厂类负责创建对象较少的情况,且客户端只需要传入工厂类的参数, ...

  5. Spring中常见的设计模式——模板模式

    一.模板模式的应用场景 模板模式又叫模板方法模式(Template Method Pattern),指定义一个算法的骨架,并允许自雷为一个或者多个步骤提供实现.模板模式使得子类可以在不改变算法结果的情 ...

  6. Spring中常见的设计模式——适配器模式

    一.适配器模式的应用场景 适配器模式(Adapter Pattern)是指将一个类的接口转换成用户期待的另一个接口,使原本接口不兼容的类可以一起工作,属于构造设计模式. 适配器适用于以下几种业务场景: ...

  7. 设计模式:JDK和Spring中常见的设计模式

    设计模式 总结 类 工厂模式 封装创建过程,只对结果负责 BeanFactory.Calender 单例模式 全局唯一 ApplicationContext.Calender 原型模式 多重影分身之术 ...

  8. Spring中常见的设计模式——单例模式

    一.单例模式的应用场景 单例模式(singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点.J2EE中的ServletContext,ServletCon ...

  9. spring 中常用的设计模式

    一. Spring 中常见的设计模式 工厂模式 : BeanFactory 装饰器模式: BeanWrapper 代理模式: AopProxy 单例模式: ApplicationContext 委派模 ...

随机推荐

  1. CCBPM工作流系统中如何在特定的一个步骤,调用起另外一条流程

    关键词: 工作流快速开发平台  工作流设计  业务流程管理   asp.net 开源工作流bpm工作流系统  java工作流主流框架  自定义工作流引擎 需求描述: 1, 操作员在操作最后一个节点时, ...

  2. 设计模式C++描述----19.命令(Command)模式

    一. 举例说明 我们知道,在多线程程序中,多个用户都给系统发 Read 和 Write 命令.这里有几点需要说明: 1. 首先明确一点,所有的这些 Read 和 Write 命令都是调用一个库函数. ...

  3. 全方面讲解TensorFlow

    任何曾经试图在 Python 中只利用 NumPy 编写神经网络代码的人都知道那是多么麻烦.编写一个简单的一层前馈网络的代码尚且需要 40 多行代码,当增加层数时,编写代码将会更加困难,执行时间也会更 ...

  4. 【XSY2344】K-th String

    Description Alice有 n(n≤26) 张牌,牌上分别标有前 n 个英文小写字母.例如,如果 n=3 ,则Alice有3张牌,分别标有"a", "b&quo ...

  5. Pandas 时间序列

    # 导入相关库 import numpy as np import pandas as pd 在做金融领域方面的分析时,经常会对时间进行一系列的处理.Pandas 内部自带了很多关于时间序列相关的工具 ...

  6. Centos7下安装nexus3.x 安装

    1.官网下载unix版本 2.上传到linux系统的/usr/目录下 [root@lmll70op-ne ~]# cd /usr/ [root@lmll70op-ne usr]# ll 3.解压,并重 ...

  7. 『题解』洛谷P1314 聪明的质监员

    更好的阅读体验 Portal Portal1: Luogu Portal2: LibreOJ Portal3: Vijos Description 小T是一名质量监督员,最近负责检验一批矿产的质量.这 ...

  8. 域名解析 | A记录 ,CNAME,MX,NS 你懂了吗

    域名解析 | A记录 ,CNAME,MX,NS 你懂了吗 域名解析 什么是域名解析?域名解析就是国际域名或者国内域名以及中文域名等域名申请后做的到IP地址的转换过程.IP地址是网路上标识您站点的数字地 ...

  9. vue-snippet-模板

    "template": { "prefix": "template", "body": [ "<temp ...

  10. php swoole异步处理mysql

    php swoole异步处理mysql <pre>//创建websocket服务器对象,监听0.0.0.0:9509端口//异步测试$ws = new swoole_websocket_s ...