什么是原型模式?
原型模式是一种对象创建型模式。
原型模式使用原型实例指定创建对象的类,并且通过拷贝这些原型创建新的对象。
Java中的克隆就是采用的原型模式。
工作或生活中,我们写的周报,记得手帐,其实每一周都是同一套实现,只是内容不一样而已,这种例子也可以用原型模式来实现。
在消息推送中,用户接收到的消息体的格式,是基本不会变化的,所以也可以使用原型模式。
核心结构
- Prototype。抽象原型类,既可以是抽象类,也可以是接口,甚至可以是某些具体实现类,主要声明了克隆方法。
- ConcretePrototype。具体原型类,实现了抽象原型类中声明的克隆方法,在克隆方法中返回一个自己的克隆对象。
- Client。客户端,原型对象的外部调用,可以根据原型对象的克隆方法获取多个克隆对象。
类图展示
代码分析
在模式介绍中,我们举了消息推送格式的例子,接下来我们就对其进行一下实现。
我们使用的是Java中已经存在的Cloneable作为抽象原型类,我们看一下这个类:
public interface Cloneable {
}
什么都没有,你让我继承什么?
别急,忘记了Object类是万物之父了?在我们背过的面试题中,肯定有这么一道题,请说出Object类中的方法,并简述其作用,方法中就有一个clone()方法,Object#clone()方法是一个本地方法。
接下来,我们实现具体原型类:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/13 0013.
* 原型模式——具体原型类
*/
public class Message implements Cloneable {
private String title;
private String content;
private String date;
public Message clone() {
Object obj;
try {
obj = super.clone();
return (Message) obj;
} catch (CloneNotSupportedException e) {
System.out.println("消息暂时不支持复制");
return null;
}
}
public void message() {
System.out.println("title: " + title + "content: " + content + "date: " + date);
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getDate() {
return date;
}
public void setData(String date) {
this.date = date;
}
}
原型模式部分已经OK。
其实外部调用就相当于客户端,客户端其实也就是我们惯例的测试代码:
/**
* Created by <sunshine> mysunshinedreams@163.com on 2017/1/13 0013.
* 原型模式测试
*/
public class CloneTest {
public static void main(String[] args) {
cloneTest();
}
private static void cloneTest() {
Message evening = null;
try {
Message model = new Message();
model.setTitle("早间新闻");
model.setContent("XXX");
model.setData("2017-01-13");
Message noon = model.clone();
noon.setTitle("午间新闻");
evening = model.clone();
evening.setTitle("晚间新闻");
model.message();
noon.message();
evening.message();
System.out.println(model == noon);
} catch (Exception e) {
e.printStackTrace();
}
}
}
模式总结
优点
- 客户根据需求直接调用克隆方法,无需了解内部实现细节,便于代码的维护和扩展。
- 使用原型模式创建的对象比重新在内存中分配对象性能更好,尤其是在使用大对象的时候。
- 原型模式和工厂模式类似,但是没有复杂的层级关系,代码结构简单清晰。
缺点
- 克隆方法位于类的内部,如果需要修改克隆方法,则破坏了开闭原则。
- 如果需要实现深克隆,则需要进行认真的编码,加大了开发者的挑战难度。
适用场景
- 大对象往复创建。
- 系统设计时,如果发现某一模型中,对象的变化很小,可以采用原型模式构造不同的实例。