原型模式

生活中有很多重复性的工作。比如写日记,每天的日记要写下当天是几月几日,天气怎样。而每天的格式是差不多的,只需要改下日期和天气,另外就是写下当天日记内容就可以了。我们可以使用原型模式,保存这个模板,每天写的时候复制一份下来修改就行了。

原型模式结构

  • 原型管理器
  • 原型接口
  • 原型具体实现

浅克隆与深克隆

当复制原型模板时涉及到对象的克隆。对象的克隆又有浅克隆和深克隆之分。浅克隆只拷贝值类型,而深克隆值类型与引用类型都拷贝。在Java中,Object的clone只实现了浅克隆。需要深克隆的话需要自己序列化对象并反序列化回来进行引用类型的拷贝。

一个简单的例子

  • Prototype
  • Address
  • Student
  • PrototypeManager
  • Client

Prototype.java

interface Prototype{
    void display();
    Prototype deepClone() throws Exception;
    void setName(String name);
    void setRoad(String road);
}

Adress.java

import java.io.*;
public class Student implements Prototype,Serializable {

    private String name;
    private Address address;

    public Student(String name, Address address){
        this.name = name;
        this.address = address;
    }

    public Prototype deepClone() throws Exception{
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bao);
        oos.writeObject(this);

        ByteArrayInputStream bai = new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bai);
        return (Prototype)ois.readObject();
    }

    public void display(){
        System.out.println(name + ",road:" + (address==null ? null : address.getRoad()));
    };

    public void setName(String name){
        this.name = name;
    }

    public void setRoad(String road){
        if(this.address != null) {
            this.address.setRoad(road);
        }
    }
}

Student.java

import java.io.*;
public class Student implements Prototype,Serializable {

    private String name;
    private Address address;

    public Student(String name, Address address){
        this.name = name;
        this.address = address;
    }

    public Prototype deepClone() throws Exception{
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bao);
        oos.writeObject(this);

        ByteArrayInputStream bai = new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bai);
        return (Prototype)ois.readObject();
    }

    public void display(){
        System.out.println(name + ",road:" + (address==null ? null : address.getRoad()));
    };

    public void setName(String name){
        this.name = name;
    }

    public void setRoad(String road){
        if(this.address != null) {
            this.address.setRoad(road);
        }
    }
}

PrototypeManager.java

import java.util.*;
public class PrototypeManager{

    private HashMap<String,Prototype> hm = new HashMap<String,Prototype>();

    public static PrototypeManager pm = new PrototypeManager();

    public static PrototypeManager getInstance(){
        return pm;
    }

    private PrototypeManager(){
        hm.put("stu",new Student("defalut",new Address("road")));
    }

    public Prototype getPrototype(String key){
        return hm.get(key);
    }
}

Client.java

public class Client{
    public static void main(String[] args){
        Prototype prototype = PrototypeManager.getInstance().getPrototype("stu");

        try{
            Prototype zhangsan = prototype.deepClone();
            zhangsan.setName("zhangsan");
            zhangsan.setRoad("GZ");

            Prototype lisi = prototype.deepClone();

            prototype.display();
            zhangsan.display();
            lisi.display();
        }catch(Exception e){
            System.out.println(e);
        }
    }
}

(完)