原型模式(Prototype Pattern)

原型模式的定义:

Specify the kinds of objects to create using a prototypical instance , and create new objects by copying this prototype .

使用原型实例指定要创建的对象类型,通过复制这个实例创建新的对象。


原型模式在生活中的应用场景:

假如你刚给自己的客厅做了装修,你朋友正好也希望给他的客厅做装修,那么,他可能把你家的装修方案拿过来改改就成,你的装修方案就是原型。


原型模式的实现:

提供一个静态工厂方法来获得原型数据,然后复制这些数据,最后做相应的初始化。为了操作安全,我们不直接使用原型数据,而是使用clone()方法从内存中克隆这条原型数据再做后续操作。在这里使用的是Java提供java.lang.Cloneable接口克隆数据。

(我们在复制新的新的数据时,需要特别注意的是,我们不能把所有数据都复制过来,例如,当对象包含主键时,不能使用原型数据的主键,必须创建一个新的主键。)


package com.alex.prototypepattern;

public class PackageInfoTestDrive {
    public static void main(String[] args) {
        PackageInfo currentInfo = PackageInfo.clonePackage("John");
        System.out.println("Original package information:");
        display(currentInfo);

        currentInfo.setId(10000l);
        currentInfo.setReceiverName("Ryan");
        currentInfo.setReceiverAddress("People Square, Shanghai");

        System.out.println("\nNew package information:");
        display(currentInfo);
    }

    private static void display(PackageInfo currentInfo) {
        System.out.println("Package id: " + currentInfo.getId());
        System.out.println("Receiver name: " + currentInfo.getReceiverName());
        System.out.println("Receiver address: " + currentInfo.getReceiverAddress());
        System.out.println("Sender name: " + currentInfo.getSenderName());
        System.out.println("Sender Phone No.: " + currentInfo.getSenderPhoneNo());
    }
}

package com.alex.prototypepattern;


public class PackageInfo implements Cloneable{
	 private Long id;
	    private String receiverName;
	    private String receiverAddress;
	    private String senderName;
	    private String senderPhoneNo;

	    //other fields, getters, setters and other methods...


	    public Long getId() {
	        return id;
	    }

	    public void setId(Long id) {
	        this.id = id;
	    }

	    public String getReceiverName() {
	        return receiverName;
	    }

	    public void setReceiverName(String receiverName) {
	        this.receiverName = receiverName;
	    }

	    public String getReceiverAddress() {
	        return receiverAddress;
	    }

	    public void setReceiverAddress(String receiverAddress) {
	        this.receiverAddress = receiverAddress;
	    }

	    public String getSenderName() {
	        return senderName;
	    }

	    public void setSenderName(String senderName) {
	        this.senderName = senderName;
	    }

	    public String getSenderPhoneNo() {
	        return senderPhoneNo;
	    }

	    public void setSenderPhoneNo(String senderPhoneNo) {
	        this.senderPhoneNo = senderPhoneNo;
	    }
	    
	public PackageInfo clone(){
		try{
			return (PackageInfo)super.clone();
		}catch(CloneNotSupportedException ex){
			System.out.println("Cloning not allowed");
			return null;
		}
	}
	
	public static PackageInfo clonePackage(String userName){
		PackageInfo prototype = loadPackageInfo(userName);
		prototype.clone();
		prototype.setId(null);
		return prototype;
	}
	
	 //Simulate loading data from database
    private static PackageInfo loadPackageInfo(String userName) {
        PackageInfo packageInfo = new PackageInfo();

        //create a String object in jvm heap not jvm string pool
        packageInfo.setId(100l);
        packageInfo.setReceiverName("John");
        packageInfo.setReceiverAddress("People Square,Shanghai");
        packageInfo.setSenderName("William");
        packageInfo.setSenderPhoneNo("12345678901");
        return packageInfo;
    }
}

运行结果:

Original package information:
Package id: null
Receiver name: John
Receiver address: People Square,Shanghai
Sender name: William
Sender Phone No.: 12345678901


New package information:
Package id: 10000
Receiver name: Ryan
Receiver address: People Square, Shanghai
Sender name: William
Sender Phone No.: 12345678901

Object 的 clone()方法的复制是采用逐字节的方式从内存复制数据,复制了对象属性的引用,而属性所指的对象本身没有复制,因此所复制的引用指向了相同的对象。用这种方式复制对象是浅拷贝,不是深拷贝。

注:本文大部分内容点来自刘济华的《漫谈设计模式》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值