[工作中的设计模式]原型模式prototype

时间:2022-12-27 22:51:46

一、模式解析

  提起prototype,最近看多了js相关的内容,第一印象首先是js的原型

var Person=function(name){
this.name=name;
}
Person.prototype.run=function(){
alert(this.name+" is running";
}

  此处的原型是js的特殊定义,在原型上定义的属性和方法所有的类进行共享。

  不过设计模式中的原型模式指的是:将已有的对象作为原型,拷贝出一份具有相同属性的新的对象。

  模式定义为:原型模式要求对象实现一个可以“克隆”自身的接口,这样就可以通过复制一个实例对象本身来创建一个新的实例。这样一来,通过原型实例创建新的对象,就不再需要关心这个实例本身的类型,只要实现了克隆自身的方法,就可以通过这个方法来获取新的对象,而无须再去通过new来创建。

  原型模式的实现主要有两种:1、继承接口clonable,实现类的拷贝,2、继承接口Serializable,将原实例序列化,然后解序列化生成新的对象。

  针对第一种拷贝,又分为深拷贝和浅拷贝。

  浅拷贝:实例中基本对象类型进行拷贝,引用对象类型仅拷贝引用地址,引用对象中的数据变化,会导致源对象和拷贝对象内容同时发生变化。

  深拷贝:除基本对象类型外,引用对象类型也会一一拷贝其内部的的数据,从而使源对象变化不会引起拷贝对象变化。

二、模式代码

浅拷贝实例:

import java.util.ArrayList;
import java.util.List; public class Prototype implements Cloneable {
public String name;//普通数据类型
public List<String> list =new ArrayList<String>();//list集合,引用数据类型
public Prototype(String name){
this.name=name;
} @Override
public Object clone(){
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
}
package prototype.patten;

public class Client {
public static void main(String[] args) {
Prototype p1=new Prototype("zhangsan");
p1.list.add("a");
p1.list.add("b");
Prototype p2=(Prototype) p1.clone();
p1.name="lisi";
System.out.println("p1.name=="+p1.name);//p1.name==lisi
System.out.println("p2.name=="+p2.name);//p2.name==zhangsan p2.list.add("c");
System.out.println(p1.list.toString());//[a, b, c]
System.out.println(p2.list.toString());//[a, b, c] }
}

可以看到基本类型name已经完全不同,p1的变化与p2无关,但list的变化仍然相关,p1增加元素会导致p2同时增加。

深拷贝实例:

package prototype.patten;

class Person implements Cloneable{
public String name;
@Override
protected Person clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return (Person)super.clone();
}
} public class DeepPrototype implements Cloneable {
public Person person;
public int count; @Override
protected DeepPrototype clone() throws CloneNotSupportedException {
DeepPrototype prototype=(DeepPrototype) super.clone();
prototype.person=this.person.clone();//内部的引用类型分别执行clone方法 return prototype;
} }
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
DeepPrototype prototype=new DeepPrototype();
Person person=new Person();
person.name="张三";
prototype.person=person;
prototype.count=10;
DeepPrototype p2=prototype.clone();
prototype.person.name="李四";
prototype.count=11;
System.out.println("prototype.person.name=="+prototype.person.name);//prototype.person.name==李四
System.out.println("p2.person.name=="+p2.person.name); //p2.person.name==张三
System.out.println("prototype.count=="+prototype.count); // prototype.count==11
System.out.println("p2.count=="+p2.count);//p2.count==10 }
}

可以看到,深拷贝的重点是在clone方法中,所有引用对象类型要执行clone的方法,深拷贝完成后,源对象和新对象的所有属性具有无关性。

因为真的引用对象也要执行clone的方法,ArrayList等方法引用了clonable和Serializable等方法,因此同意可以实现深拷贝

序列化深克隆

 public  Object deepClone() throws IOException, ClassNotFoundException{
//将对象写到流里
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//从流里读回来
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}

只要实现了接口Serializable,均可以编写此方法,然后通过调用方法完成深克隆,无需考虑参数类型。

三、模式应用场景

  在工作中目前还没有主动使用clone方法实现对象的创建,序列化方式的保存和复制对象在系统日志等非接化数据中进行使用,不过并非原型模式。

  接触的比较接近与模板方式应用的例子是jquery源码中类的继承使用,由于jquery没有直接的继承方法,因此有与多人开发了如原型继承,混合继承的方法,jquery使用的是对象拷贝继承,可以根据参数选择,实现深拷贝或浅拷贝,算上原型模式的实例化最接近的例子。

四、模式代码

jQuery.extend = jQuery.fn.extend = function() {
var src, copyIsArray, copy, name, options, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false; // Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
} // Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
} // extend jQuery itself if only one argument is passed
if ( length === i ) {
target = this;
--i;
} for ( ; i < length; i++ ) {
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null ) {
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ]; // Prevent never-ending loop
if ( target === copy ) {
continue;
} // Recurse if we're merging plain objects or arrays
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
if ( copyIsArray ) {
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : []; } else {
clone = src && jQuery.isPlainObject(src) ? src : {};
} // Never move original objects, clone them
target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}

[工作中的设计模式]原型模式prototype的更多相关文章

  1. PHP设计模式 原型模式&lpar;Prototype&rpar;

    定义 和工厂模式类似,用来创建对象.但实现机制不同,原型模式是先创建一个对象,采用clone的方式进行新对象的创建. 场景 大对象的创建. 优点 1.可以在运行时刻增加和删除产品 2.可以改变值或结构 ...

  2. &lbrack;工作中的设计模式&rsqb;建造者模式builder

    一.模式解析 建造模式是将复杂的内部创建封装在内部,对于外部调用的人来说,只需要传入建造者和建造工具,对于内部是如何建造成成品的,调用者无需关心. 以上是对建造者模式的官方定义,简单说就是对于复杂对象 ...

  3. C&num;设计模式——原型模式&lpar;Prototype Pattern&rpar;

    一.概述 在软件开发中,经常会碰上某些对象,其创建的过程比较复杂,而且随着需求的变化,其创建过程也会发生剧烈的变化,但他们的接口却能比较稳定.对这类对象的创建,我们应该遵循依赖倒置原则,即抽象不应该依 ...

  4. 设计模式-原型模式&lpar;Prototype&rpar;

    场景分析: 前面我们提到,交易对象Trade,还有继承他的债券交易BondTrade.期货交易FutureTrade. 现在有一个需求,需要提供方法将交易拆分成多笔小交易. 代码如下(如果没有clon ...

  5. 设计模式——原型模式&lpar;Prototype&rpar;

    用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象.——DP UML类图 模式说明 如果把在一张纸上手写一篇简历的过程看成是类的实例化过程,那么通过原型模式创建对象的过程就是拿着这张纸到复印 ...

  6. 设计模式--原型模式Prototype(创建型)

    一.原型模式 用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象.原型模式实现的关键就是实现Clone函数,还需要实现深拷贝. 二.UML类图 三.例子 //父类 class Resume ...

  7. &lbrack;工作中的设计模式&rsqb;解释器模式模式Interpreter

    一.模式解析 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器.客户端可以使用这个解释器来解释这个语言中的句子. 以上是解释器模式的类图,事实上我 ...

  8. &lbrack;工作中的设计模式&rsqb;中介模式模式Mediator

    一.模式解析 用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互. 中介模式又叫调停者模式,他有如下特点: 1.有多个系统或者对 ...

  9. 谈谈设计模式~原型模式&lpar;Prototype&rpar;

    返回目录 原型模式是创建型模式的一种,其特点在于通过“复制”一个已经存在的实例来返回新的实例(clone),而不是新建(new)实例.被复制的实例就是我们所称的“原型”,这个原型是可定制的. 原型模式 ...

随机推荐

  1. JDBC Tutorials&colon; Commit or Rollback transaction in finally block

    http://skeletoncoder.blogspot.com/2006/10/jdbc-tutorials-commit-or-rollback.html JDBC Tutorials: Com ...

  2. IOS RunLoop浅析 三

    经过两篇的介绍我想对RunLoop应该有了简单的了解,至少不至于一无所知. 在这篇我想对“CFRunLoopObserverRef”做一下简单的补充. 在补充之前先说一下. 在现在的开发中已经很少见到 ...

  3. 处理大并发之五 使用libevent利器bufferevent

    转自:http://blog.csdn.net/feitianxuxue/article/details/9386843 处理大并发之五 使用libevent利器bufferevent 首先来翻译一段 ...

  4. install chrome in elementary os

    Elementary OS Freya 0.3.2 was officially out for public. As previous release, it comes pre-installed ...

  5. NSFileManager 沙盒文件管理

    文件夹创建,复制,移动,删除,检查是否存在,代码如下: 1.获取沙盒 document 路径,作为文件夹路径的基路径. NSString *document = NSSearchPathForDire ...

  6. &ast;&ast;&ast; Terminating app due to uncaught exception &&num;39&semi;NSUnknownKeyException&&num;39&semi;&comma; reason&colon; &&num;39&semi;&lbrack;ViewController &gt&semi; setValue&colon;forUndefinedKey&colon;&rsqb;&colon; this class is not key value coding-compliant for the key

    *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ViewController > ...

  7. 介质共享型局域网中的介质访问控制(MAC)协议需要具体解决的3个问题,CSMA&sol;CD介质访问控制的基本思想

    1,在某一时刻,那个节点可以发送数据 2,发送时是否会出现冲突 3,出现冲突时如何处理 CSMA/CD介质访问控制的基本思想:先监听,再发送.边发送,边监听,如发生冲突,则等待一段时间后再次发送

  8. LeetCode题解之 Find the Town Judge

    1.题目描述 2.问题分析 使用map set数据结构. 3.代码 int findJudge(int N, vector<vector<int>>& trust) { ...

  9. Linux 性能分析调优 (四)——案例篇:系统中出现大量不可中断进程和僵尸进程怎么办

    之前讲到 CPU 使用率的类型.除了上一节提到的用户 CPU 之外,它还包括系统 CPU(比如上下文切换).等待 I/O 的 CPU(比如等待磁盘的响应)以及中断 CPU(包括软中断和硬中断)等. 在 ...

  10. MySQL5&period;7的安装(CentOS 7 &amp&semi; Ubuntu 16&period;04)

    CentOS 通过 yum 安装MySQL5.7 Yum Repository 下载地址:https://dev.mysql.com/downloads/repo/yum/ 选择相应的版本进行下载:R ...