设计模式二——原型模式
来源:互联网 发布:腾讯高级php面试题 编辑:程序博客网 时间:2024/06/06 00:34
写在前面:对于原型模式的介绍,网上有很多。但是给我的感觉,有些介绍并不是在单纯的介绍原型模式本身的意义,而是附加了其他的设计模式。至少我在看过很多文章之后,不仅未清晰的了解原型模式的本质,反而愈发感觉糊里糊涂。当然,这或许是我个人还没达到理解这种模式的水平。
本文关于原型模式的介绍,基本是出于我个人依据定义的理解。或许是正确的,或许存在谬误,欢迎大家留言指正讨论。
目录
- 目录
- 一模式定义分析
- 1实现对象复制之前先回顾一下以下知识点
- 2哪些场景下应该考虑使用复制的模式呢
- 3复制在哪里操作需要注意什么
- 二代码实现
- 1原型类代码
- 2调用类代码
- 三补充说明
- 四参考文章
首先看下原型模式的定义:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
Prototype原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。
一、模式定义分析
通过上面的定义,得到的关键词是:对象复制。那我们就从对象和复制展开来讨论。
1、实现对象复制之前先回顾一下以下知识点:
- 在Java中,对象实例的创建一般都要通过new关键字,需要通过构造函数来实例化。既然要复制,可能要避开这个限制。
- 在Java中,创建的对象除去基本数据类型的非包装类、字符串对象(在JDK7之前,待考证)等,绝大多数的对象都是在堆内存中创建的。复制,就需要在内存空间中创建出一个独立的对象出来。
- 在Java中,提供了语言级别的复制支持,那就是Cloneable接口。这个接口是个标记接口,里面并没有要实现的方法。因为所有的对象都隐式的继承自Object类,Object类中有一个clone方法。这个clone方法有2个限制:①方法修饰符是protected,无法在非继承类内部使用,所以要在重写时把修饰符改为public。②如果没有实现Cloneable接口而直接调用clone方法,会报错。
- 对象中既有基本数据类型的成员变量,也有可能有引用类型的成员变量,拷贝方式肯定有区别。所以需要了解浅拷贝和深拷贝的概念。
2、哪些场景下应该考虑使用复制的模式呢?
因为和复制做对比的,主要是通过new关键字来创建对象,所以来看下new可能会遇到的性能问题。
①当new对象需要大量繁琐的准备工作时,复制会提高性能。
示例场景public Demo getDemoInstance() { Object obj = prepareObject();// 创建对象前需要执行一些耗时操作 Demo demo = new Demo(obj);}public Demo(Object obj) { // 解析配置、初始化环境、设置变量等等操作}
②当需要多次重复的调用new关键字执行构造函数时,累积的时间损耗也是可以考虑的优化点。
for(int i=0; i<1000000; i++) { Demo demo = new Demo(); // 每次都要新建对象,而new又比较耗时的时候 handle(demo);}
③当一个对象创建耗时,单实例又存在并发安全问题时,也可以考虑复制一份。
写到这里忍不住想起ThreadLocal类,这个号称为每个线程拷贝一份副本的类是怎么实现的?深拷贝还是浅拷贝呢?拷贝时如果泛型里的类没有实现Cloneable接口会怎样呢?回头再去看看...
3、复制在哪里操作?需要注意什么?
- 尽量减少new对象的地方,如果系统中大量通过new创建的对象,那么复制也就没啥意义了
- 复制需要在用到原型类对象的地方来操作
二、代码实现:
1、原型类代码
public class Prototype implements Cloneable { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); }
2、调用类代码
public class PrototypeClient { public static void main(String[] args) throws CloneNotSupportedException { Prototype raw = new Prototype(); for (int i=0; i<1000; i++) { Prototype clone = (Prototype) raw.clone(); System.out.println(clone); } }}
三、补充说明:
综上,复制之前我们需要先有一个现成的对象,但是这个现成的对象数量不宜过多,否则就失去了复制的意义。原始对象可以考虑使用缓存的方式、单例模式等。
四、参考文章:
原型模式|菜鸟教程
设计模式之原型模式
【JAVA】设计模式之原型模式的使用分析
0 0
- 设计模式二——原型模式
- 设计模式—原型模式
- 设计模式—原型模式
- 设计模式—原型模式
- 设计模式—原型模式
- 设计模式——原型设计模式
- 设计模式——原型设计模式
- Prototype —原型模式二
- iOS设计模式解析(二) —— 原型
- 浅谈设计模式——原型模式
- 设计模式——原型模式(Prototype)
- 原型模式——设计模式系列
- 设计模式——原型模式
- 设计模式——原型模式
- java设计模式——原型模式
- 原型模式——设计模式系列
- 【大话设计模式】—— 原型模式
- C++设计模式——原型模式
- 从印度增长最快的在线教育公司窥视印度在线教育行业现状
- request.getAttribute()与request.setAttribute()与session.setAttribute()
- IOS开发笔记7-C语言基础复习
- Cockroach Design 翻译 ( 八) 严格序列化(线性化)
- STM32--MDK仿真调试:逻辑分析仪的使用
- 设计模式二——原型模式
- android JNI (NDK)的故事
- Cockroach Design 翻译 ( 九) 逻辑Map内容、store和存储
- 写给准备开始作死的自己 :书签记录
- Cockroach Design 翻译 ( 十) 自修复、重平衡
- C#工厂模式-从简单到优雅的几种实践
- android某包的功能突然用不了
- Cockroach Design 翻译 ( 十一) range元数据
- 三序遍历以及Vertical Order