一、概述
原型模式是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
二、代码
1.创建一个实现了 Clonable 接口的抽象类。
public abstract class Sender implements Cloneable {
protected String id ;
protected String type;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
abstract void sendMessage();
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}
2.创建扩展了上面抽象类的实体类。
public class MessageSender extends Sender {
public MessageSender() {
type = "message";
}
@Override
void sendMessage() {
System.out.println("send a message");
}
}
public class SMSSender extends Sender{
public SMSSender() {
type = "SMS";
}
@Override
void sendMessage() {
System.out.println("send a sms");
}
}
3.创建一个类,获取实体类,并把它们存储在一个 Hashtable 中。
public class SenderCache {
private static Hashtable
senderMap = new Hashtable<>();
public static Sender getSender(String sendreID){
Sender sender = senderMap.get(sendreID);
return (Sender) sender.clone();
}
/*每种情况需要进行数据库查询*/
public static void loadCache(){
MessageSender messageSender = new MessageSender();
messageSender.setId("1");
senderMap.put(messageSender.getId(),messageSender);
SMSSender smsSender = new SMSSender();
smsSender.setId("2");
senderMap.put(smsSender.getId(),smsSender);
}
}
4.测试
public class PrototypePatternDemo {
public static void main(String[] args) {
SenderCache.loadCache();
MessageSender messageSender = (MessageSender) SenderCache.getSender("1");
SMSSender smsSender = (SMSSender)SenderCache.getSender("2");
System.out.println("Message:"+messageSender.getType());
System.out.println("SMSSender:"+smsSender.getType());
}
}
PS:
- 浅拷贝对于要克隆的对象, 会复制其基本数据类型(包括String)的属性(本例中的typr属性)的值给新的对象. 而对于非基本数据类型的属性(如集合属性), 仅仅复制一份引用给新产生的对象, 即新产生的对象和原始对象中的非基本数据类型的属性都指向的是同一个对象.
- 深拷贝 对于要克隆的对象, clone出的非基本数据类型的属性(要求属性也实现了Cloneable接口, ArrayList就已经自带实现了)不再是和原对象指向同一个对象了, 而是一个新的clone出来的属性对象实例.