创建型设计模式之原型模式
Posted 丨Jack_Chen丨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了创建型设计模式之原型模式相关的知识,希望对你有一定的参考价值。
原型模式
概述
优缺点
优点:
1.java自带的原型模式是基于内存二进制流的拷贝,比直接new一个对象性能上提升许多
2.使用原型模式将对象复制一份并将其状态保存起来,简化创建对象的过程,以便在需要的时候使用
缺点:
1.需要为每一个类配置一个克隆方法
2克隆方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违反开闭原测
3.在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支特深克隆,实现比较麻烦
应用场景
1.类初始化消耗资源较多
2.new产生的一个对象需要非常繁琐的过程(数据准备或访问权限)
3.构造函数处比较复杂
4.循环体中生产大量对象时
5.资源优化场景
6.性能和安全要求的场景
主要角色
1.客户(Client)角色
2.抽象原型(Prototype)角色
3.具体原型(Concrete Prototype)角色
4.原型管理器(Prototype Manager)角色
原型模式的基本使用
创建原型接口
public interface IPrototype<T>
T clone();
创建具体需要克隆对象
@Data
@ToString
public class ConcretePrototype implements IPrototype
private int age;
private String name;
@Override
public ConcretePrototype clone()
ConcretePrototype concretePrototype = new ConcretePrototype();
concretePrototype.setAge(this.age);
concretePrototype.setName(this.name);
return concretePrototype;
使用
public static void main(String[] args)
//创建原型对象
ConcretePrototype prototype = new ConcretePrototype();
prototype.setAge(20);
prototype.setName("jack");
System.out.println(prototype);
//拷贝原型对象
ConcretePrototype cloneType = prototype.clone();
System.out.println(cloneType);
JDK自带原型接口的使用
@Data
@ToString
public class ConcretePrototype implements Cloneable
private int age;
private String name;
private List<String> hobbies;
@Override
public ConcretePrototype clone()
try
return (ConcretePrototype)super.clone();
catch (CloneNotSupportedException e)
e.printStackTrace();
return null;
浅克隆与深度克隆
浅克隆
@Data
@ToString
public class ConcretePrototype implements Cloneable
private int age;
private String name;
private List<String> hobby;
@Override
public ConcretePrototype clone()
try
return (ConcretePrototype)super.clone();
catch (CloneNotSupportedException e)
e.printStackTrace();
return null;
public static void main(String[] args)
ConcretePrototype prototype = new ConcretePrototype();
prototype.setAge(22);
prototype.setName("jack");
List<String> hobby = new ArrayList<String>();
hobby.add("java");
hobby.add("python");
hobby.add("go");
prototype.setHobby(hobby);
// 拷贝原型对象
ConcretePrototype cloneType = prototype.clone();
cloneType.getHobby().add("php");
System.out.println("原型对象:" + prototype);
System.out.println("克隆对象:" + cloneType);
System.out.println(prototype == cloneType);
System.out.println(prototype.getHobby() == cloneType.getHobby());
原型对象:ConcretePrototype(age=22, name=jack, hobby=[java, python, go, php])
克隆对象:ConcretePrototype(age=22, name=jack, hobby=[java, python, go, php])
false
true
深度克隆
可使用序列化方式实现对象的深度克隆
@Data
@ToString
public class ConcretePrototype implements Cloneable, Serializable
private int age;
private String name;
private List<String> hobby;
@Override
public ConcretePrototype clone()
try
return (ConcretePrototype) super.clone();
catch (CloneNotSupportedException e)
e.printStackTrace();
return null;
public ConcretePrototype deepClone()
try
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (ConcretePrototype) ois.readObject();
catch (Exception e)
e.printStackTrace();
return null;
public static void main(String[] args)
//创建原型对象
ConcretePrototype prototype = new ConcretePrototype();
prototype.setAge(22);
prototype.setName("jack");
List<String> hobby = new ArrayList<String>();
hobby.add("java");
hobby.add("python");
hobby.add("go");
prototype.setHobby(hobby);
// 拷贝原型对象
ConcretePrototype cloneType = prototype.deepClone();
cloneType.getHobby().add("php");
System.out.println("原型对象:" + prototype);
System.out.println("克隆对象:" + cloneType);
System.out.println(prototype == cloneType);
System.out.println(prototype.getHobby() == cloneType.getHobby());
原型对象:ConcretePrototype(age=22, name=jack, hobby=[java, python, go])
克隆对象:ConcretePrototype(age=22, name=jack, hobby=[java, python, go, php])
false
false
也可这样操作,多克隆一次
public ConcretePrototype deepClone2()
try
ConcretePrototype result = (ConcretePrototype) super.clone();
result.hobby = (List) ((ArrayList) result.hobby).clone();
return result;
catch (CloneNotSupportedException e)
e.printStackTrace();
return null;
单例的破坏
解决方案:禁止深克隆。
1.让单例类不实现Cloneable接口
2.重写clone方法,在clone方法中返回单例对象即可
@Data
@ToString
public class ConcretePrototype implements Cloneable
private static ConcretePrototype instance = new ConcretePrototype();
private ConcretePrototype()
public static ConcretePrototype getInstance()
return instance;
@Override
public ConcretePrototype clone()
return instance;
以上是关于创建型设计模式之原型模式的主要内容,如果未能解决你的问题,请参考以下文章