原型模式(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.可以改变值或结构 ...
随机推荐
- timestamp的自动更新 ON UPDATE CURRENT_TIMESTAMP
最近有一个关于MySQL版本升级的事,涉及到一些关于时间类型的细节问题需要查明,因此到官网找到相关文章,翻出来比较方便自己理解,博客这里也贴一下. 参考官网网址: https://dev.mysql. ...
- 旋转矩形碰撞检测 OBB方向包围盒算法
在cocos2dx中进行矩形的碰撞检测时需要对旋转过的矩形做碰撞检查,由于游戏没有使用Box2D等物理引擎,所以采用了OBB(Oriented bounding box)方向包围盒算法,这个算法是基于 ...
- joda 获取每个月第一天第一秒和最后一天最后一秒
/** * 获取每个月第一天的第一秒 * @return */ public static final Date getMouthOfFirst(){ DateTimeFormatter format ...
- <jquery>基本的模态框
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- springboot整合mybatis进行跨库查询
业务场景: 当一个公司大了之后就会将各种业务进行分开,最简单的就是例如:公司的机构表,那么就会将他们分成开来,那么就会在一个实例中, 如果要获取相关信息就会去关联这张表进行关联查询 从而导致了跨库关联 ...
- 9个永恒的UI设计原则
很多人都在寻找那些能够帮助他们快速提升设计能力的方法,但你是否想过,自己身上的哪些方面会对你的设计产生影响呢?是使用工具的技巧,对设计的理解和态度,还是你的生活习惯呢?我想说所有这些都是决定你的设计是 ...
- 如何为ABAP程序添加权限检查
一.确认权限对象,及其关联字段: TCode: SU21 例如权限对象"M_MSEG_WMB",它关联字段为"WERKS",详见下图: 二.在ABAP代码中添加 ...
- SwiftUI 实现Draggesture效果
今天闲来无事,使用SwiftUI 实现拖动,并且返回的动态效果.代码不多..... 效果如下: 代码如下: import SwiftUI import Combine class KBDragObje ...
- [转]C#的扩展方法解说
C#的扩展方法解说 扩展方法的目的就是为一个现有类型添加一个方法,现有类型既可以是int,string等数据类型,也可以是自定义的数据类型. 为数据类型的添加一个方法的理解:一般来说,int数据类型有 ...
- 第十一章 Odoo 12开发之看板视图和用户端 QWeb
QWeb 是 Odoo 使用的模板引擎,它基于 XML 来生成 HTML 片断和页面.通过 QWeb可生成内容丰富的看板(Kankan)视图.报表和 CMS 网页.本文中我们将学习QWeb 语法以及如 ...