7、Prototype 原型模式 通过复制创造实例 创造型模式
其实上一节的末尾讲到如何去生成对象,其中有一个关于clone的,这其实就是Prototype原型模式. 通过克隆(拷贝)的方式生成对象
1、了解Prototype原型模式
引文:
在商品房销售系统中,房屋信息是基础信息。在系统运行前必须输入房屋的各种信息到系统中,这是一项枯燥的重复劳动。如果让用户重复输入房间的类型、面积和卫生间样式,这个系统肯定尚未运行就夭折了。实际上,一个小区楼盘的样式并不多,不同的只是楼号。另外,楼盘中的房间类型也非常有限,从而为解决输入问题提供了启示。所以我们可以事先创建一个楼盘模型,然后复制出更多的楼盘模型。复制后,只需要调整一下楼号等信息即可。原型模式也可以用来解决这类问题。
定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
类型:创建类模式
类图:
原型模式是一种比较简单的模式,也非常容易理解,实现一个接口,重写一个方法即完成了原型模式。在实际应用中,原型模式很少单独出现。经常与其他模式混用,他的原型类Prototype也常用抽象类来替代。
Java中的实现方式:
1:implement Cloneable(此接口是clone()的声明,记住是规范就完事了)
2:重写Object的clone方法(涉及到浅拷贝和深拷贝)
注意:
深拷贝与浅拷贝问题中,会发生深拷贝的有java中的8中基本类型以及他们的封装类型,另外还有String类型。其余的都是浅拷贝。
2、浅拷贝
浅拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象.
定义一只Sheep 羊
package cn.design.prototype; import java.util.Date; /**
* @author lin
* @version 1.0
* @date 2020/7/19 21:09
* @Description 羊
*/
public class Sheep implements Cloneable {
String name;
Date birthDay; public Sheep(String name, Date birthDay) {
this.name = name;
this.birthDay = birthDay;
} @Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Date getBirthDay() {
return birthDay;
} public void setBirthDay(Date birthDay) {
this.birthDay = birthDay;
}
}
定义测试TestClone1
package cn.design.prototype; import java.util.Date; /**
* @author lin
* @version 1.0
* @date 2020/7/19 21:11
* @Description 浅克隆 测试类
*/
public class TestClone1 {
public static void main(String[] args) throws CloneNotSupportedException {
Date date = new Date(21312312312L);
Sheep s1 = new Sheep("小利", date);
System.out.println("s1 = " + s1);
System.out.println("s1.getName() = " + s1.getName());
System.out.println("s1.getBirthDay() = " + s1.getBirthDay()); System.out.println(); Sheep s2 = (Sheep) s1.clone();
System.out.println("s2 = " + s2);
System.out.println("s2.getName() = " + s2.getName());
System.out.println("s2.getBirthDay() = " + s2.getBirthDay()); System.out.println(); // 拷贝完成之后 , 可以对 新对象进行修改
s2.setName("多利");
System.out.println("s2.getName() = " + s2.getName());
// 对比s1
System.out.println("s1.getName() = " + s1.getName()); System.out.println(); // 浅拷贝的问题 , 就是 内部 是引用的 date对象, 如果拷贝的新对象修改了 date对象, 则 源对象的date也被修改
date.setTime(435345353453L);
s2.setBirthDay(date); System.out.println("s2.getBirthDay() = " + s2.getBirthDay());
// 对比s1
System.out.println("s1.getBirthDay() = " + s1.getBirthDay()); }
}
运行结果如下:
s1 = cn.design.prototype.Sheep@135fbaa4
s1.getName() = 小利
s1.getBirthDay() = Sat Sep 05 00:05:12 CST 1970 s2 = cn.design.prototype.Sheep@7ea987ac
s2.getName() = 小利
s2.getBirthDay() = Sat Sep 05 00:05:12 CST 1970 s2.getName() = 多利
s1.getName() = 小利 s2.getBirthDay() = Wed Oct 19 01:15:53 CST 1983
s1.getBirthDay() = Wed Oct 19 01:15:53 CST 1983
3、深拷贝
深拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制.
浅拷贝的升级版,更注重全属性的拷贝。
定义Sheep2类
package cn.design.prototype; import java.util.Date; /**
* @author lin
* @version 1.0
* @date 2020/7/19 21:09
* @Description 羊2
*/
public class Sheep2 implements Cloneable {
String name;
Date birthDay; public Sheep2(String name, Date birthDay) {
this.name = name;
this.birthDay = birthDay;
} @Override
protected Object clone() throws CloneNotSupportedException {
Date newDate = null;
Sheep2 o = (Sheep2) super.clone();
newDate = (Date) o.birthDay.clone();
o.setBirthDay(newDate);
return o;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Date getBirthDay() {
return birthDay;
} public void setBirthDay(Date birthDay) {
this.birthDay = birthDay;
}
}
定义测试类TestClone2
package cn.design.prototype; import java.util.Date; /**
* @author lin
* @version 1.0
* @date 2020/7/19 21:11
* @Description 浅克隆 测试类
*/
public class TestClone2 {
public static void main(String[] args) throws CloneNotSupportedException {
Date date = new Date(21312312312L);
Sheep2 s1 = new Sheep2("小利", date);
System.out.println("s1 = " + s1);
System.out.println("s1.getName() = " + s1.getName());
System.out.println("s1.getBirthDay() = " + s1.getBirthDay()); System.out.println(); Sheep2 s2 = (Sheep2) s1.clone();
System.out.println("s2 = " + s2);
System.out.println("s2.getName() = " + s2.getName());
System.out.println("s2.getBirthDay() = " + s2.getBirthDay()); System.out.println(); // 拷贝完成之后 , 可以对 新对象进行修改
s2.setName("多利");
System.out.println("s2.getName() = " + s2.getName());
// 对比s1
System.out.println("s1.getName() = " + s1.getName()); System.out.println(); // 对比浅拷贝, 测试 深拷贝
date.setTime(435345353453L);
s1.setBirthDay(date); System.out.println("s2.getBirthDay() = " + s2.getBirthDay());
// 对比s1
System.out.println("s1.getBirthDay() = " + s1.getBirthDay()); }
}
运行结果如下:
s1 = cn.design.prototype.Sheep2@4ac68d3e
s1.getName() = 小利
s1.getBirthDay() = Sat Sep 05 00:05:12 CST 1970 Sat Sep 05 00:05:12 CST 1970
Sat Sep 05 00:05:12 CST 1970
s2 = cn.design.prototype.Sheep2@27082746
s2.getName() = 小利
s2.getBirthDay() = Sat Sep 05 00:05:12 CST 1970 s2.getName() = 多利
s1.getName() = 小利 s2.getBirthDay() = Sat Sep 05 00:05:12 CST 1970
s1.getBirthDay() = Wed Oct 19 01:15:53 CST 1983
与目标VM断开连接, 地址为: ''127.0.0.1:14378', transport: '套接字'', 传输: '{1}' Process finished with exit code 0
4、运用场景?
1、资源优化场景
类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
2、性能和安全要求的场景:
通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
3、一个对象多个修改者的场景
一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与Java融为浑然一体,大家可以随手拿来使用。
5、小结
1、Prototype模式用于隔离类对象的使用者和具体类型(易变类)的之间的耦合关系,但是这些易变类必须拥有稳定的接口.
2、Prototype模式对于"如何创建易变类的对象"采用"原型克隆"的方式来做,它使我们能非常灵活动态的创建某些拥有"稳定接口"的新对象.所需的工作仅仅是创建一个新类的对象即原型,然后在需要的地方不断的Clone.
3、Prototype模式的Clone方法可以利用Object自带的MemberwiseClone方法,注:该方法只能用于比较简单的类,只能实现浅拷贝,如果类中包含数组等引用类型,则需要使用序列化方法来实现类型的深拷贝
发哥讲
如果你觉得文章还不错,就请点击右上角选择发送给朋友或者转发到朋友圈~
● 扫码关注公众号, 转载请备注来源,和链接
7、Prototype 原型模式 通过复制创造实例 创造型模式的更多相关文章
- 8、Builder 建造者模式 组装复杂的实例 创造型模式
1.什么是Builder模式 定义: 将一个复杂对象的构建与表示相分离,使得同样的构建过程可以创建不同的表示.大白话就是,你不需要知道这个类的内部是什么样的,只用把想使用的参数传进去就可以了,达到了解 ...
- [WCF编程]7.实例上下文模式
一.实例上下文模式概述 实例上下文(IntanceContext Mode)表示服务端的服务实例与客户端的服务代理的绑定方式. 在实例化服务器对象时,WCF采用了3种不同的模式:单调(Per-Call ...
- C++设计模式-Prototype原型模式
作用: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. Prototype模式提供了一个通过已存在对象进行新对象创建的接口(Clone), Clone()实现和具体的语言相关,在C+ ...
- 设计模式(五):PROTOTYPE原型模式 -- 创建型模式
1.定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 2.适用场景 原型模式的主要思想是基于现有的对象克隆一个新的对象出来,一般是有对象的内部提供克隆的方法,通过该方法返回一个对 ...
- js原生设计模式——7原型模式之真正的原型模式——对象复制封装
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- 设计模式(1)--Prototype(原型模式)--创建型
1.模式定义: 原型模式就是用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象. 2.使用场景: 在原型模式中我们可以利用过一个原型对象来指明我们所要创建对象的类型,然后通过复制这个对象的 ...
- Java设计模式:Prototype(原型)模式
概念定义 使用原型实例指定待创建对象的种类,并通过拷贝该原型来创建新的对象.Prototype模式允许一个原型对象克隆(复制)出多个与其相同的对象,而无需知道任何如何创建的细节. 应用场景 对象的创建 ...
- 一天一个设计模式——Prototype 原型模式
一.模式说明 看了比较多的资料,对原型模式写的比较复杂,个人的理解就是模型复制,根据现有的类来直接创建新的类,而不是调用类的构造函数. 那为什么不直接调用new方法来创建类的实例呢,主要一个原因是如果 ...
- prototype原型模式中的问题
对于每个构造函数来说,都有一个prototype属性.对于每个对象实例来说,都有_proto_属性. 参看下面代码: function Person(){} Person.prototype={ na ...
随机推荐
- 让 axios 支持 finally
当我们执行一个promise操作时,往往伴随的是要做各种状态的修改(如请求开始时显示loading,结束时隐藏 loading), 这个状态修改,如果没有finally函数,我们需要在then和cat ...
- Lodash中数组常用方法
数组方法 1.数组对象去重 differenceBy(array, [values], [iteratee=_.identity]) let newArr =_.differenceBy( [{ na ...
- bootstrap中模态框如果放入form表单中会存在的问题
bootstrap中模态框如果放入form表单中会存在的问题:当模态框显示时,点回车会出现表单自动提交!!!所以在使用模态框的时候要特别注意!
- Burp Suite Extender Module - 扩展模块
模块功能: 在扩展模块可以通过使用自定义代码,进行Burp 的自定义操作. 1. Burp Extensions页面 2. BApp Store中可以购买和安装别人写好的扩展功能 3. 在APIs界面 ...
- Python Ethical Hacking - BeEF Framework(1)
Browser Exploitation Framework. Allows us to launch a number of attacks on a hooked target. Targets ...
- 如何看待HTTP/3
前言 HTTP/2 相比于 HTTP/1.1,可以说是大幅度提高了网页的性能,只需要升级到该协议就可以减少很多之前需要做的性能优化工作,当然兼容问题以及如何优雅降级应该是国内还不普遍使用的原因之一. ...
- accpet和connect设置超时
三次握手 TCP连接建立的开始是三次握手,通过三次交互确认连接成功,在客户端调用connect时,客户端发送sync消息给服务端,服务端收到sync消息后,返回一个ack+sync,并等待ack,客户 ...
- Python3基础语法快速入门
01 Python 简介 Python 是一种高层次的结合了解释性.编译性.互动性和面向对象的脚本语言.Python 由 Guido van Rossum 于 1989 年底在荷兰国家数学和计算机科学 ...
- .log文件超过2.56MB?Pycharm的.log文件读取不完全?.log文件无法被调用?
问题截图: 问题表现情况: 1.pycharm头部出现上图警告 2.该.log文件读取不完全 3.该.log文件无法被调用 解决步骤: 参考博客:https://blog.csdn.net/Shen1 ...
- springboot(4)Druid作为项目数据源(添加监控)
参考博客:恒宇少年:https://www.jianshu.com/p/e84e2709f383 Druid简介 Druid是一个关系型数据库连接池,它是阿里巴巴的一个开源项目.Druid支持所有JD ...