设计模式快速理解原型模式,及其在源码中的应用
Posted Java鱼仔
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式快速理解原型模式,及其在源码中的应用相关的知识,希望对你有一定的参考价值。
(一)什么是原型模式
在正常的开发过程中,百分之99的对象实例都是通过new进行创建的,但是在实际的场景中,还是存在一些不通过new生成对象实例的应用场景。
比如:需要生成大量类似的对象实例时,如果都通过new去创建,性能并不好。
又比如:通过很复杂的方式生成了一个对象,现在要再创建出一个类似的对象出来。
上面的两种应用场景都可以通过“拷贝”这个动作来实现,这种根据一个已有的原型对象,拷贝生成新的对象的方式,就是设计模式中的原型模式(prototype)。
在Java中,可以通过Cloneable接口和clone方法很好地实现原型模式。
(二)原型模式的简单例子
首先通过一个简单的例子让大家快速了解原型模式。
过年的时候公司给每个人发了一份邮件,这个邮件里除了署名和入职年份不一样以外,其他的内容都是相同的。比如:张三,这是你入职的第一年,祝你新年快乐XXXXX;李四,这是你入职的第二年,祝你新年快乐XXXXX。
这里的每一份邮件都可以理解为一个对象,而所有的对象实例都是相似的对象实例,因此就可以实用原型模式来拷贝生成这些重复的对象。
首先创建一个邮件对象,需要实现Cloneable接口:
public class Mail implements Cloneable
private String name;
private String content;
private Integer years;
Mail(String name,String content,Integer years)
this.name = name;
this.content = content;
this.years = years;
System.out.println("对象创建成功");
private void showMail()
System.out.println(name+",这是你入职的第"+years+"年,"+content);
@Override
protected Object clone() throws CloneNotSupportedException
System.out.println("拷贝成功");
return super.clone();
public void setContent(String content)
this.content = content;
public void setName(String name)
this.name = name;
public void setYears(Integer years)
this.years = years;
接下来在使用的时候先通过new创建一个基础对象实例,其他的均通过clone进行拷贝:
public static void main(String[] args) throws CloneNotSupportedException
Mail mail = new Mail("张三", "祝你新年快乐XXXXXX", 1);
mail.showMail();
Mail cloneMail = (Mail) mail.clone();
cloneMail.setName("李四");
cloneMail.setYears(2);
mail.showMail();
这样一个简单的原型模式就实现了。
(三)基于管理器的原型模式
上面的例子可以增加对原型模式的理解,在实际开发中,更常用的是使用一个管理器去管理原型对象,可以在管理器类中通过一个HashMap保存原型对象。以水果店为例子。
首先定义了一个接口叫做Fruit,里面有两个方法:,shape方法用于展示水果的外观,createFruit方法用于通过克隆创建原型对象实例。
public interface Fruit extends Cloneable
void shape();
Object createFruit() throws Exception;
接着定义管理器,管理器由HashMap进行管理,提供注册和创建实例的功能:
public class FruitManager
private HashMap<String,Fruit> managerMap = new HashMap<>();
public void register(String name,Fruit fruit)
managerMap.put(name,fruit);
public Fruit create(String name) throws Exception
Fruit fruit = managerMap.get(name);
return (Fruit) fruit.createFruit();
下一步就是定义两个具体的对象,需要注意的是createFruit()方法使用了clone()进行拷贝:
public class Apple implements Fruit
@Override
public void shape()
System.out.println("苹果是红色的圆形水果");
@Override
public Object createFruit() throws Exception
return super.clone();
public class Orange implements Fruit
@Override
public void shape()
System.out.println("橘子是黄色的圆形水果");
@Override
public Object createFruit() throws Exception
return super.clone();
最后写一个测试方法:
public static void main(String[] args) throws Exception
FruitManager manager = new FruitManager();
//注册到管理器中
manager.register("apple",new Apple());
manager.register("orange",new Orange());
//通过create方法不断拷贝新的对象
Fruit apple = manager.create("apple");
apple.shape();
Fruit orange = manager.create("orange");
orange.shape();
(四)原型模式在源码中的应用
其实在很多地方都用到了原型模式,比如最常用的ArrayList,同样定义了clone方法供调用者进行拷贝。
抛去Cloneable相关的接口,一些对象之间的复制操作也是原型模式的实践,比如Spring里BeanUtils.copyProperties()这个方法,同样实现了根据一个已有的原型对象,拷贝生成新的对象。
(五)总结
本章内容主要通过两个例子讲解了原型模式的概念以及应用,我是鱼仔,我们下期再见!
以上是关于设计模式快速理解原型模式,及其在源码中的应用的主要内容,如果未能解决你的问题,请参考以下文章