程序猿学社的GitHub,欢迎Star
github技术专题
本文已记录到github
通过前面两章,我们已经知道单例模式,工厂模式,本文就来看一看原型模式。
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式属于一种创建型的设计模式
隔壁老王: “社长,你们公司需要填写周报吗?”
社长: “需要填写的,而且每周,都会有一次周例会”
隔壁老王: “填写周报好浪费时间,还得排版,再填写内容”
社长: “你是怎么实现的”
隔壁老王: “我每次重新生成一个excel,再排版的”
社长: “老铁,你这太实诚咯”
package com.cxyxs.designmode.prototype;
import lombok.Data;
import java.util.Date;
/**
* Description:
* Author: 程序猿学社
* Date: 2020/4/12 18:42
* Modified By:
*/
@Data
public class Weekly {
private String name;
/** 本周计划 */
private String weekPlan;
/** 下周计划 */
private String nextWeekPlan;
/** 填写时间 */
private Date createTime;
public Weekly(String name, String weekPlan, String nextWeekPlan, Date createTime) {
this.name = name;
this.weekPlan = weekPlan;
this.nextWeekPlan = nextWeekPlan;
this.createTime = createTime;
}
}
package com.cxyxs.designmode.prototype;
import java.util.Date;
/**
* Description:
* Author: 程序猿学社
* Date: 2020/4/12 18:45
* Modified By:
*/
public class WeeklyTest {
public static void main(String[] args) {
Weekly weekly = new Weekly("隔壁小王","用户模块开发","订单模块开发",new Date());
System.out.println("--------本周周报--------");
System.out.println(weekly.toString());
System.out.println("--------下周周报--------");
Weekly weekly1 = new Weekly("隔壁小王","订单模块开发","订单模块开发相关单元测试",new Date());
System.out.println(weekly1.toString());
}
}
隔壁老王: “社长,有没有什么方法,可以简化周报这块,提高我编写周报的效率”
社长: “直接copy一份,上一次编写的周报(原型模式),在此之上,再做修改”
package com.cxyxs.designmode.prototype.shallow;
import lombok.Data;
import java.util.Date;
/**
* Description:
* Author: 程序猿学社
* Date: 2020/4/12 18:42
* Modified By:
*/
@Data
public class Weekly implements Cloneable{
private String name;
/** 本周计划 */
private String weekPlan;
/** 下周计划 */
private String nextWeekPlan;
/** 填写时间 */
private Date createTime;
public Weekly(String name, String weekPlan, String nextWeekPlan, Date createTime) {
this.name = name;
this.weekPlan = weekPlan;
this.nextWeekPlan = nextWeekPlan;
this.createTime = createTime;
}
@Override
protected Object clone() throws CloneNotSupportedException {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
通过上面的代码,我们小小的梳理一下,实现的过程
实现原型模式就两步:
package com.cxyxs.designmode.prototype.shallow;
import java.util.Date;
/**
* Description:
* Author: 程序猿学社
* Date: 2020/4/12 18:45
* Modified By:
*/
public class WeeklyTest {
public static void main(String[] args) throws Exception{
Date date = new Date();
Weekly weekly = new Weekly("隔壁小王","用户模块开发","订单模块开发",date);
System.out.println("--------本周周报--------");
System.out.println(weekly.toString());
System.out.println("--------下周周报--------");
Weekly weekly1 = (Weekly) weekly.clone(); //使用克隆(copy方式)
//Weekly weekly1 = new Weekly("隔壁小王","订单模块开发","订单模块开发相关单元测试",new Date());
System.out.println(weekly1.toString());
System.out.println(weekly == weekly1);
}
}
社长: “实际上,上面这种写法还存在一点的问题”
隔壁老王: “社长,存在什么问题”
社长: “上面这种写法,只能实现浅克隆,没有实现完全的克隆,我们先通过一个例子来看一看把”
package com.cxyxs.designmode.prototype.shallow;
import java.util.Date;
/**
* Description:
* Author: 程序猿学社
* Date: 2020/4/12 18:45
* Modified By:
*/
public class WeeklyTest1 {
public static void main(String[] args) throws Exception{
Date date = new Date();
Weekly weekly = new Weekly("隔壁小王","用户模块开发","订单模块开发",date);
Weekly weekly1 = (Weekly) weekly.clone(); //使用克隆(copy方式)
System.out.println(weekly.toString());
System.out.println(weekly1.toString());
//修改克隆后对象的值
date.setTime(1546315871);
System.out.println("--------------");
System.out.println(weekly.toString());
System.out.println(weekly1.toString());
}
}
浅克隆
package com.cxyxs.designmode.prototype.shallow;
import lombok.Data;
import java.util.Date;
/**
* Description:
* Author: 程序猿学社
* Date: 2020/4/12 18:42
* Modified By:
*/
@Data
public class Weekly implements Cloneable{
private String name;
/** 本周计划 */
private String weekPlan;
/** 下周计划 */
private String nextWeekPlan;
/** 填写时间 */
private Date createTime;
public Weekly(String name, String weekPlan, String nextWeekPlan, Date createTime) {
this.name = name;
this.weekPlan = weekPlan;
this.nextWeekPlan = nextWeekPlan;
this.createTime = createTime;
}
@Override
protected Object clone() throws CloneNotSupportedException {
try {
Weekly weekly = (Weekly) super.clone();
//把数据克隆
Date clone = (Date) createTime.clone();
weekly.setCreateTime(clone);
return weekly;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
隔壁老王: “社长,看了一下,你写的代码,这还是属性的,如果有上百个属性,我这一个个改,也忒麻烦咯。有没有不用这样一个个设置的方法”
社长: “这种方法的copy,实际上是内存的copy,直接操作内存的,也是性能最好的,如果你觉得这种方式太麻烦了,我们可以通过序列化和反序列的方式来实现”
package com.cxyxs.designmode.prototype.shallow.seri;
import lombok.Data;
import java.io.*;
import java.util.Date;
/**
* Description:
* Author: 程序猿学社
* Date: 2020/4/12 18:42
* Modified By:
*/
@Data
public class Weekly implements Serializable {
private String name;
/** 本周计划 */
private String weekPlan;
/** 下周计划 */
private String nextWeekPlan;
/** 填写时间 */
private Date createTime;
public Weekly(String name, String weekPlan, String nextWeekPlan, Date createTime) {
this.name = name;
this.weekPlan = weekPlan;
this.nextWeekPlan = nextWeekPlan;
this.createTime = createTime;
}
public Object copy() throws Exception{
//序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
Weekly weekly = (Weekly) ois.readObject();
return weekly;
}
}
实现序列化两部曲:
package com.cxyxs.designmode.prototype.shallow.seri;
import java.util.Date;
/**
* Description:
* Author: 程序猿学社
* Date: 2020/4/12 18:45
* Modified By:
*/
public class WeeklyTest2 {
public static void main(String[] args) throws Exception{
Date date = new Date();
Weekly weekly = new Weekly("隔壁老王","用户模块开发","订单模块开发",date);
Weekly weekly1 = (Weekly) weekly.copy(); //使用克隆(copy方式)
System.out.println(weekly.toString());
System.out.println(weekly1.toString());
//修改克隆后对象的值
date.setTime(11);
System.out.println("--------------");
System.out.println(weekly.toString());
System.out.println(weekly1.toString());
}
}
总结: 如果,需要创建大量的对象,建议使用原型模式。实际上他是不符合ocp原则的。应该实现对扩展开放,对修改关闭。不会调用类的重构方法 ,可以破解单例模式。
原创不易,不要白嫖,觉得有用的社友,给我点赞,让更多的老铁看到这篇文章。
因技术能力有限,如文中有不合理的地方,希望各位大佬指出,在下方评论留言,谢谢,希望大家一起进步,一起成长。
作者:程序猿学社
原创公众号:『程序猿学社』,专注于java技术栈,分享java各个技术系列专题,以及各个技术点的面试题。
原创不易,转载请注明来源(注明:来源于公众号:程序猿学社, 作者:程序猿学社)。