原型模式(Prototype)(对象、克隆广告邮件)
有些对象创建过程较为复杂,而且有些时候需要频繁的创建,原型模式通过给出一个原型对象来指明所要创建的对象的类型,然后复制这个原型对象的方法创建更多同类型的对象。这就是原型模式的动机。
原型模式的主要思想是基于现有对象克隆一个新的对象出来,一般是有对象的内部提供克隆的方法,通过该方法返回一个对象的副本。在以下几个场景中,使用原型模式会更简单效率也更高。
(1)当一个系统应该独立于它的产品创建、构成和表示时,要使用原型模式。
(2)当要实例化的类是在运行时刻指定时,例如:动态装载。
(3)为了避免创建一个与产品类层次平行的类层次时。
(4)当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆他们可能比每次用合适的状态手工实例化该类更方便一些(也就是当我们在处理一些比较简单的对象,并且对象之间的区别很小,可能只是很固定的几个属性不同的时候,使用原型模式更合适)。
原型模式主要用于对象的复制,它的核心是原型类Prototype。Prototype类需要具备以下两个条件:
(1)实现Cloneable接口: JAVA语言中有一个Cloneable接口,他的作用只用一个,就是在运行时通知虚拟机可以安全的在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被复制,否则会抛出异常CloneNotSupportedExceotion
(2)重写Object类中的clone方法。clone()作用是返回对象的一个复制,但其作用域是protected类型的,一般的类无法调用,因此,Prototype类需要将clone方法作用域改为public。
原型模式实现广告模板克隆:
广告模板:
public class Adv {
private String subject;
private String contxt;
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getContxt() {
return contxt;
}
public void setContxt(String contxt) {
this.contxt = contxt;
}
}
mail类 实现可对自身进行克隆:
/*
* 实现Cloneable 接口 可以对自身进行克隆
*/
public class Mail implements Cloneable{
private String recrviver = "AAA";
private String subject = "BBB";
private String appellation = "CCC";
private String tail = "DDD";
private String contxt = "EEE"; public Mail() {
super();
}
public Mail(Adv adv) {
contxt = adv.getContxt();
subject = adv.getSubject();
}
@Override
public Mail clone() {
Mail mail = null;
try { //为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的clone()识别出你要复制的是哪一个对象
// 然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中
mail= (Mail) super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return mail;
} @Override
public String toString() {
return "Mail [recrviver=" + recrviver + ", subject=" + subject + ", appellation=" + appellation + ", tail=" + tail
+ ", contxt=" + contxt + "]";
}
public String getRecrviver() {
return recrviver;
}
public void setRecrviver(String recrviver) {
this.recrviver = recrviver;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getAppellation() {
return appellation;
}
public void setAppellation(String appellation) {
this.appellation = appellation;
}
public String getTail() {
return tail;
}
public void setTail(String tail) {
this.tail = tail;
}
public String getContxt() {
return contxt;
}
public void setContxt(String contxt) {
this.contxt = contxt;
} }
测试类:
public class Test {
public static void main(String[] args) {
// Mail m1 = new Mail();
// Mail m2 = m1.clone();
// System.out.println( m2.toString());
Mail mail= new Mail(new Adv());//Adv是广告的模板
for(int i = 0; i<5;i++){
Mail m = mail.clone();//克隆原型邮件
m.setRecrviver(""+i);//向邮件中添加不同的收件信息
System.out.println(m.toString());
}
}
}
Mail [recrviver=0, subject=null, appellation=CCC, tail=DDD, contxt=null]
Mail [recrviver=1, subject=null, appellation=CCC, tail=DDD, contxt=null]
Mail [recrviver=2, subject=null, appellation=CCC, tail=DDD, contxt=null]
Mail [recrviver=3, subject=null, appellation=CCC, tail=DDD, contxt=null]
Mail [recrviver=4, subject=null, appellation=CCC, tail=DDD, contxt=null]
⑴浅复制(浅克隆)
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象内存储的引用,而不复制它所引用的对象。
⑵深复制(深克隆)
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
从以下我们可以看出,clone所进行的时浅克隆们m2只复制了m1所存储的引用当我们对m2做出更改时m1也会改变:
public static void main(String[] args) {
Mail m1 = new Mail();
Mail m2 = m1.clone();
System.out.println( m2.toString());
System.out.println(m1.equals(m2));
System.out.println(m1.getAppellation().equals(m2.getAppellation()));
// Mail mail= new Mail(new Adv());//Adv是广告的模板
// for(int i = 0; i<5;i++){
// Mail m = mail.clone();//克隆原型邮件
// m.setRecrviver(""+i);//向邮件中添加不同的收件信息
// System.out.println(m.toString());
//
// }
}
}
Mail [recrviver=AAA, subject=BBB, appellation=CCC, tail=DDD, contxt=EEE] false true
实现深克隆时需要编写的代码会比较复杂,当对象的嵌套结构复杂时由于要实现深克隆,每一层的类都必须支持深克隆。实现起来会比较复杂。
(1)使用原型模式复制不会调用类的构造方法,因为对象的复制是通过调用object类的clone方法来完成的,它直接在内存中复制数据,因此不会调用到类的构造方法,
(2)构造方法中的代码不会执行,甚至脸访问权限都对原型模式无效,所以单例模式与原型模式是冲突的。
原型模式(Prototype)(对象、克隆广告邮件)的更多相关文章
- 设计模式系列之原型模式(Prototype Pattern)——对象的克隆
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
- Net设计模式实例之原型模式( Prototype Pattern)
一.原型模式简介(Brief Introduction) 原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. Specify the kin ...
- [工作中的设计模式]原型模式prototype
一.模式解析 提起prototype,最近看多了js相关的内容,第一印象首先是js的原型 var Person=function(name){ this.name=name; } Person.pro ...
- 二十四种设计模式:原型模式(Prototype Pattern)
原型模式(Prototype Pattern) 介绍用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象.示例有一个Message实体类,现在要克隆它. MessageModel usin ...
- 设计模式(四)原型模式Prototype(创建型)
设计模式(四)原型模式Prototype(创建型) 1. 概述 我们都知道,创建型模式一般是用来创建一个新的对象,然后我们使用这个对象完成一些对象的操作,我们通过原型模式可以快速的创建一个对象 ...
- 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)
原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...
- 原型模式-Prototype(Java实现)
原型模式-Prototype 通过复制(克隆.拷贝)一个指定类型的对象来创建更多同类型的对象. 就像去蛋糕店买蛋糕一样. 柜台里的蛋糕都是非卖品. 只是为顾客提供一种参照. 当顾客看上某一个样式的蛋糕 ...
- 原型模式 prototype 创建型 设计模式(七)
原型模式 prototype 意图 用原型实例指定需要创建的对象的类型,然后使用复制这个原型对象的方法创建出更多同类型的对象 显然,原型模式就是给出一个对象,然后克隆一个或者更多个对象 小时候看 ...
- PHP设计模式 原型模式(Prototype)
定义 和工厂模式类似,用来创建对象.但实现机制不同,原型模式是先创建一个对象,采用clone的方式进行新对象的创建. 场景 大对象的创建. 优点 1.可以在运行时刻增加和删除产品 2.可以改变值或结构 ...
随机推荐
- JS switch 分支语句
描述:根据一个变量的不同取值,来执行不同的代码. 语法结构: switch(变量) { case 值1: 代码1; break; case 值2: 代码2; break; case 值3: 代码3; ...
- day22_1-课前上节复习+os模块
# ********************day22_1-课前上节复习+os模块 *******************# ********************day22_1-课前上节复习+os ...
- <随便写>同步,异步进程池,线程
from multiprocessing import Pool import time import os def work(n): print("%s run" % os.ge ...
- mac系统升级导致无法在iOS设备中运行Safari Web 调试器
macOS系统升级之后,可能会导致Safari开发选项中没有iOS设备,进而无法运行Safari Web 调试器. 此问题的解决办法: 请转到设置>常规>重置>重置位置和隐私.现在, ...
- PHP网络请求优化
目录 1. 设置超时时间 2. 将串行请求并行化 1. 设置超时时间 连接超时:200ms 读超时: 800ms 写超时: 500ms 2. 将串行请求并行化 使用curl_multi_*() 使用s ...
- 锋利的Jquery(Table,Checkbox)
1.Table奇数偶数行 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http: ...
- [ javasript ] javascript中的each遍历!
1.数组中的each var arr = [ "one", "two", "three", "four"]; $.eac ...
- 项目接入即时聊天客服系统(环信系统)PHP后端操作
环信工作原理: 一.由于环信没有直接的接口来主动调取本项目中的用户数据,所有用户信息必须在环信服务器上注册对应信息成为环信的用户:(这样才能当用户进入聊天时显示其基本信息,如:名称.昵称.电话.邮箱等 ...
- 杂项-SpringBoot-Jasypt:Jasypt(安全框架)
ylbtech-杂项-SpringBoot-Jasypt:Jasypt(安全框架) 1. 使用jasypt加密Spring Boot应用中的敏感配置返回顶部 1. 本文讲述了在Spring Boot/ ...
- Delphi的日志库
1. 安装 Log4D下载: 官网地址 LoggerPro下载 GitHub地址 特点: log4d简单易用.性能稳定 LoggerPro貌似功能很强大,只是没有详细的文档,懒得翻源码 安装步骤 Lo ...