原型设计模式
创始人
2024-03-01 02:43:22

一、原型模式

1、定义

原型模式(Prototype Pattern)指原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象,属于创建型设计模式。

原型模式的核心在于复制原型对象。

2、结构

(1)模式的结构

主要角色如下:

  • 客户类(Client):客户类提出创建对象的请求
  • 抽象原型(Iprototype):规定复制接口。
  • 具体原型(ConcretePrototype):被复制的对象。

注意:不是通过直接 new关键字而是通过复制对象来实现创建对象的模式被称作原型模式。

3、优缺点

优点:

  • Java自带的原型模式基于内存二进制流的复制,在性能上比直接 new更好。
  • 通过深拷贝方式保存对象状态,简化创建对象的过程。

缺点:

  • 需要为每一个类都配置一个 clone方法。
  • clone方法位于类的内部,如果对已有类进行改造时,需要修改代码,违背了开闭原则。
  • 当对象之间存在多重嵌套引用时,使用深拷贝会比较麻烦,每一层对象对应的类都必须支持深拷贝。

4、使用场景

  • 创建对象成本较大,需要优化资源
  • 系统中大量使用该类对象,并且各个调用者都需要它的属性重复赋值。

5、在框架源码中使用

二、模式的通用实现

代码如下:

public class PrototypePattern {public static void main(String[] args) {ConcretePotrotypeA potrotypeA = new ConcretePotrotypeA();potrotypeA.setDesc("ConcretePotrotypeA");ConcretePotrotypeA clone = potrotypeA.clone();clone.setDesc("clone");System.out.println(potrotypeA);System.out.println(clone);}
}/*** 抽象原型* * @param */
interface IPrototype {// 复制T clone();
}/*** 具体原型*/
class ConcretePotrotypeA implements IPrototype {private String desc;@Overridepublic ConcretePotrotypeA clone() {// 进行复制ConcretePotrotypeA concretePotrotypeA = new ConcretePotrotypeA();concretePotrotypeA.setDesc(this.getDesc());return concretePotrotypeA;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}@Overridepublic String toString() {return "ConcretePotrotypeA{" + "desc='" + desc + '\'' + '}';}
}

三、模式的应用实例

1、浅拷贝

Java内置了 Cloneable抽象原型接口,自定义的类只需要实现该接口并重写 Object.clone()方法即可完成本类的复制。

在这里插入图片描述

一般使用 clone方法,需要满足几个条件:

  • 对任何对象,都有 o.clone() != o。即克隆对象与原型对象不是同一个对象。
  • 对任何对象,都有 o.clone().getClass() = o.getClass()。即克隆对象与原型对象的类型一样。
  • 如果对象 o的 equals()方法定义恰当,则 o.clone().equals(o) 应当成立,可选条件。

代码如下;

public class ConcretePotrotypeB implements Cloneable{private String desc;private List userList;/*** 浅拷贝* @return*/@Overrideprotected ConcretePotrotypeB clone(){ConcretePotrotypeB clone = null;try {/*** super.clone()方法是基于内存二进制流的复制*/clone = (ConcretePotrotypeB) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return clone;}// get/set}

测试:

	public static void main(String[] args) {ConcretePotrotypeB potrotypeB = new ConcretePotrotypeB();potrotypeB.setDesc("ConcretePotrotypeB");List userList = new ArrayList<>();userList.add("赵云");userList.add("后裔");potrotypeB.setUserList(userList);ConcretePotrotypeB clone = potrotypeB.clone();clone.setDesc("clone");clone.getUserList().add("安琪拉");System.out.println(potrotypeB);System.out.println(clone);System.out.println(clone == potrotypeB);System.out.println(clone.getClass() == potrotypeB.getClass());System.out.println(clone.equals(potrotypeB));}

在这里插入图片描述

注意:

  • 浅拷贝:如果类中存在引用对象属性,则原型对象与克隆对象的该属性会执行同一对象属性的引用。
  • super.clone()方法:是直接从堆内存中以二进制流的方式进行复制,重新分配一个内存块,因此其效率很高。

2、深拷贝

针对引用对象属性的深拷贝, 手动给克隆对象的该属性分配另一块内存即可。在 Java中,如果想要完成原型对象的深克隆,通常使用序列化(Serializable )的方式来完成。

代码如下;

public class ConcretePotrotypeC implements Cloneable, Serializable {private String desc;private List userList;/*** 浅拷贝* * @return*/@Overrideprotected ConcretePotrotypeC clone() {return deepClone();}/*** 深拷贝* * @return*/public ConcretePotrotypeC 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);return (ConcretePotrotypeC) ois.readObject();} catch (Exception e) {e.printStackTrace();return null;}}// get/set
}

测试:

	public static void main(String[] args) {ConcretePotrotypeC potrotypeC = new ConcretePotrotypeC();potrotypeC.setDesc("ConcretePotrotypeC");List userList = new ArrayList<>();userList.add("赵云");userList.add("后裔");potrotypeC.setUserList(userList);ConcretePotrotypeC clone = potrotypeC.clone();clone.setDesc("clone");clone.getUserList().add("安琪拉");System.out.println(potrotypeC);System.out.println(clone);System.out.println(clone == potrotypeC);System.out.println(clone.getClass() == potrotypeC.getClass());System.out.println(clone.equals(potrotypeC));}

在这里插入图片描述

参考文章:

  • 一文读懂浅拷贝和深拷贝区别:https://blog.51cto.com/u_14977428/2545103

– 求知若饥,虚心若愚。

相关内容

热门资讯

北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...