Java设计模式-原型模式

本文详细介绍了Java中的原型模式,包括定义、clone方法和Cloneable接口、浅拷贝与深拷贝的区别,以及如何利用序列化实现深拷贝。通过实例展示了如何使用原型模式复制AWM和玛莎拉蒂对象,同时讨论了该模式的优缺点。
摘要由CSDN通过智能技术生成

一、简介

1.1 定义

定义原型(Prototype)模式属于创建者模式。通过创建一个实例作为原型,并且通过复制这些原型来创建新的对象。

  • 原型对象需要提供一个方法(实现clone()方法),让该原型对象调用此方法可以复制一个和自己有相同状态的同类型对象
  • 原型对象和克隆出的新对象可以分别独立的变化。比如:我们复制一个word文档中的文本,然后创建一个新的word文档,我们可以对两个文档中的内容进行修改且互不影响。

1.2 clone方法和Cloneable接口

clone()方法

  1. clone()方法用来创建并返回此对象的拷贝,是Object类中的一个protected权限的方法,因为Object是超级父类,因此所有的类都继承了clone()方法,但在其他类中不能直接调用clone()方法
  2. 若要调用clone()方法,该类必须实现Cloneable接口。如果没有实现Cloneable接口的类的实例调用了clone()方法,则会在运行时抛出CloneNotSupportedException异常

Cloneable接口

Cloneable接口中没有任何方法,该接口的唯一作用就是表示实现该接口的对象可以被克隆

public class A{
    public static void main(String[] args) throws CloneNotSupportedException {
        B obj1 = new B();
        B obj2 = (B) obj1.clone();
        System.out.println("obj1==obj2?" + (obj1 == obj2));
    }
}

//具体原型类
class B implements Cloneable {
    B() {
        System.out.println("创建成功实例B!");
    }
    public Object clone() throws CloneNotSupportedException {
        System.out.println("原型B复制成功!");
        return (B) super.clone();
    }
}
//执行结果
创建成功实例B!
原型B复制成功!
obj1==obj2?false

1.3 浅拷贝和深拷贝

浅拷贝(浅复制、浅克隆)

Java中的数据类型分为基本数据类型和引用数据类型。

  • 基本数据类型:浅拷贝会将所有的基本数据类型String类型的数据复制一份到新的对象中去
    在这里插入图片描述
  • 引用数据类型:对于引用型变量,浅拷贝只会复制该对象的引用(内存地址),并不会复制这个引用型变量所指向的对象。
    在这里插入图片描述

深拷贝(深复制、深克隆)

深拷贝和浅拷贝的不同在于:深拷贝不仅会复制对象的引用,还会复制引用所指向的对象
在这里插入图片描述

1.4 利用序列化实现深拷贝

序列化和反序列化

  • 把对象写到流里的过程是序列化过程;
  • 把对象从流中读出来的过程则叫反序列化过程。
  • 在Java语言里深度克隆一个对象,先使对象实现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();
    }
}

二、模式原理

2.1 模式组成

组成(角色)作用
Prototype(抽象原型)一个接口,负责定义对象复制自己的方法,可以替换为Cloneable接口
ConcretePrototype(具体原型)实现Prototype接口的类,实现克隆自己的操作
Client(客户类)让一个原型对象克隆自己,创建一个新的对象

2.2 UML类图

在这里插入图片描述

三、实例

通过原型模式来克隆一把AWM一辆玛莎拉蒂

3.1 实例代码

  • 创建具体原型类:创建AWM和Maserati原型
//AWM原型
public class AWM implements Cloneable {

	// 颜色和子弹数
	public String color;
	public int ziDan;

	public AWM(String color,int ziDan) {
		this.color = color;
		this.ziDan = ziDan;
	}

	
	@Override
	public String toString() {
		return "AWM [color=" + color + ", ziDan=" + ziDan + "]";
	}


	public Object clone() {
		AWM awm = null;

		try {
			// 调用Object的clone方法,然后强制转换为Maserati类型
			awm = (AWM) super.clone();

		} catch (Exception e) {
			System.out.println(e);
		}

		return awm;
	}
}
//玛莎拉蒂原型
public class Maserati implements Cloneable {

	//颜色和耗损
	public String color;
	public int hp;
	
	public Maserati(String color,int hp){
		this.color = color;
		this.hp = hp;
	}
	
	@Override
	public String toString() {
		return "Maserati [color=" + color + ", hp=" + hp + "]";
	}

	public Object clone() {

		Maserati maserati = null;
		
		try {
			// 调用Object的clone方法,然后强制转换为Maserati类型
			maserati = (Maserati)super.clone();
			
		} catch (Exception e) {
			System.out.println(e);
		}
		return maserati;
	}
}
  • 利用原型模式复制AWM和Maserati
public class Client {
	public static void main(String[] args) {

		
		//创建一把AWM:输入颜色和子弹
		AWM awm = new AWM("black",20);
		
		//复制一把awm
		AWM awm2 = (AWM)awm.clone();
		
		System.out.println(awm.toString()+"   awm.hashCode="+awm.hashCode());
		System.out.println(awm2.toString()+"   awm2.hashCode="+awm2.hashCode());
		System.out.println(awm == awm2);
		//创建一辆玛莎拉蒂:输入颜色和hp
		Maserati maserati = new Maserati("red",100);
		
		//复制一辆玛莎拉蒂
		Maserati maserati2 = (Maserati)maserati.clone();
		
		System.out.println(maserati.toString()+"   maserati.hashCode="+maserati.hashCode());
		System.out.println(maserati2.toString()+"   maserati2.hashCode="+maserati2.hashCode());
		System.out.println(maserati == maserati2);
	}
}
//执行结果
AWM [color=black, ziDan=20]   awm.hashCode=1284693
AWM [color=black, ziDan=20]   awm2.hashCode=31168322
false
Maserati [color=red, hp=100]   maserati.hashCode=17225372
Maserati [color=red, hp=100]   maserati2.hashCode=5433634
false

3.2 UML类图

在这里插入图片描述

四、优缺点

4.1 优点

  • 当创建新实例的代价更大时,使用原型模式复制一个已有的实例可以提高创建新实例的效率
  • 利用clone()方法创建对象要比使用new创建对象快
  • 可以在不修改其他代码的情况下添加新的产品

4.2 缺点

  • 每一个类都需要有一个clone方法
  • clone()方法在类的内部,当对已有的类进行修改时,需要修改源代码,违背了开闭原则
  • 实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值