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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[工作中的设计模式]原型模式prototype相关的知识,希望对你有一定的参考价值。

一、模式解析

  提起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的方法,java的集合接口均为引用clonable接口,没有实现clone方法,所以凡是带有集合的类均无法实现深拷贝,这也是拷贝方法实现原型的阻碍。

 

序列化深克隆

 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,均可以编写此方法,然后通过调用方法完成深克隆,无需考虑参数类型。

 

以上是关于[工作中的设计模式]原型模式prototype的主要内容,如果未能解决你的问题,请参考以下文章

原型模式(Prototype)

设计模式之原型(prototype)模式

设计模式之原型模式(Prototype)详解及代码示例

java设计模式之Prototype 原型模式(浅拷贝和深拷贝)纯干货

创建者模式之原型模式

原型模式--- prototype