原型模式
原型模式属于创建型模式,用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象!(但是学姐是不可复制的哦,只有我这里有,还不赶快关注我的 Java精选频道 )
小故事引入
自上篇继续讲故事
我向学姐请教了建造者模式,她以很生动的例子给我讲了一下!让我理解地很透彻,我们一起学习到了了很晚!“忆难弟弟,我们一起把拦精灵用了吧!”,学姐说道!我便委婉的点点头!紧接着,学姐慢慢的把我按在床上,仔细的看着我的脸,此时观察学姐,那两颗小虎牙衬托出学姐的呆萌,湿润的嘴唇确实好看,软软的,恨不得去咬一下…
“好了,先去洗澡了!”,我对学姐说道。学姐从我身上慢慢的起开,“一起吗?”,“好呀!”,我们的对话变得奇怪了起来!接着我准备了两套睡衣,因为没有女生的睡衣,所以只能让学姐穿我的,可能有点大吧!学姐要先换上睡衣,我扭过去头!等学姐换好之后,我让学姐先去,我换上睡衣随后就到。学姐拿上“拦精灵”就先往洗浴间去了。我家的洗浴间还是那种比较大的,有两个浴缸,所以,是可以同时两个人洗澡的。我换上睡衣之后,便去了洗浴间把热水放开,撒上玫瑰花瓣,别有一番格调!水温刚刚好,这可能是很舒服的一个晚上…
学姐脱下睡衣,看着学姐的性感后背,身形苗条,皮肤如雪,脑后露出一头乌云般的秀发,再加上那烟雾缭绕的白气衬托,真是差点让人失去理智!
因为我们的手机都不防水,此时此刻,“拦精灵”就起到作用了!正好有两个,我们便把“拦精灵”套在手机上,这样就起到了防水的作用,可以边泡澡边玩手机了。“我们来下象棋吧!”,我说道,接着我们俩边泡澡边下起了象棋。其实有一次,我边泡澡边用手机下象棋,不小心把手机掉进水里了!但是这次不一样,有了“拦精灵”的保护,再也不怕手机进水!
哈哈,学姐的棋艺虽然高超,但是还是缺乏一些理智的“战术”,最终,学姐还是被我征服了!学姐哪有那么容易认输,接着我们又接二连三玩了几把,但是学姐依旧没有赢。泡的差不多了,这把象棋还玩在一半,于是,我让这点学姐,让她赢了一把,以便改改我这个“直男”的性格!当学姐赢了以后,开心的笑了起来!泡澡泡的很舒服,泡完澡后,我打开了一瓶红酒,拿出两个酒杯,倒上了酒。边下象棋边喝红酒,估计也只有我俩能干的出来了!
唉,这篇故事又要结束了,来讲讲原型模式吧!收起听故事的小心思,和我一起来看看原型模式!下篇接着这篇剧情讲故事、讲技术!
下篇文章:Java 适配器模式-难道学姐这是吃醋了么?…让你以最生动的例子记住适配器模式
原型模式Demo
下了几次棋,学弟把学姐征服了多少次?这里是以次为单位,我们需要把这个枢纽创建出来,为下棋计单位!
/**
* 枢纽:单位,次
*/
public class Hinge {
private String unit;
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
}
接着学姐和学弟下棋来举例,先来个学弟和学姐的下棋类,并实现Cloneable接口!
Cloneable其实就是一个标记接口,只有实现这个接口后,然后在类中重写Object中的clone方法,然后通过类调用clone方法才能克隆成功,如果不实现这个接口,则会抛出 CloneNotSupportedException 异常。
/**
* 学弟和学姐的下棋类
*/
public class PlayChess implements Cloneable {
//和漂亮学姐下棋的次数
private int num;
//和漂亮学姐下棋的单位
private Hinge hinge;
public PlayChess(int num, Hinge hinge) {
this.num = num;
this.hinge = hinge;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public Hinge getHinge() {
return hinge;
}
public void setHinge(Hinge hinge) {
this.hinge = hinge;
}
/**
* 重写clone方法
*
* @return
* @throws CloneNotSupportedException
*/
@Override
protected PlayChess clone() throws CloneNotSupportedException {
return (PlayChess) super.clone();
}
}
该具备的都具备了,现在就可以下棋了!
/**
* 学姐的原型模式
*
* @author CSDN程忆难
* @link https://myhub.blog.csdn.net
*/
public class Prototype {
public static void main(String[] args) {
//单位
Hinge hinge = new Hinge();
hinge.setUnit("次");
//这是第一次和学姐下棋
PlayChess money = new PlayChess(1, hinge);
for (int i = 0; i < 20; i++) {
try {
//克隆
PlayChess playChess = money.clone();
playChess.setNum(i + 1);
System.out.println("这是学弟和学姐 第 " + playChess.getNum() + " " + playChess.getHinge().getUnit() + "下棋 学姐输了 | 学姐被学弟 征服了 " + playChess.getNum() + " " + playChess.getHinge().getUnit());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
}
程序结构是这样的:
好了,开始下棋,让学弟征服学姐吧!!!
这就是原型模式的基本使用
使用原型模式的好处
- 提高性能;
- 不用频繁new对象;
- 消耗的资源少。
浅克隆和深克隆
介绍一下浅克隆和深克隆!
浅克隆
下棋和征服不仅仅可以用次数来表示,还可以通过局这个单位,来举个例子!我在第24行,将单位改成了局!
/**
* 学姐的原型模式
*
* @author CSDN程忆难
* @link https://myhub.blog.csdn.net
*/
public class Prototype {
public static void main(String[] args) {
//单位
Hinge hinge = new Hinge();
hinge.setUnit("次");
//这是第一次和学姐下棋
PlayChess money = new PlayChess(1, hinge);
for (int i = 0; i < 20; i++) {
try {
PlayChess playChess = money.clone();
playChess.setNum(i + 1);
hinge.setUnit("局");
System.out.println("这是学弟和学姐 第 " + playChess.getNum() + " " + playChess.getHinge().getUnit() + "下棋 学姐输了 | 学姐被学弟 征服了 " + playChess.getNum() + " " + playChess.getHinge().getUnit());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
}
然后看到运行结果全部改成了局
仔细观察代码你会发现,只是把原型的单位改了一下,但克隆的实例也跟着改变了!!!
这是因为实例对象指向了同一个内存地址,这其实就是浅克隆!
深克隆
实现深克隆,需要修改两处,保证指向的不是同一个内存地址就可以!
让枢纽也实现Cloneable接口:
/**
* 枢纽:单位,次
*/
public class Hinge implements Cloneable {
private String unit;
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
@Override
protected Hinge clone() throws CloneNotSupportedException {
return (Hinge) super.clone();
}
}
修改一下下棋方法,下棋的时候增加克隆Hinge类
/**
* 学弟和学姐的下棋类
*/
public class PlayChess implements Cloneable {
//和漂亮学姐下棋的次数
private int num;
//和漂亮学姐下棋的单位
private Hinge hinge;
public PlayChess(int num, Hinge hinge) {
this.num = num;
this.hinge = hinge;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public Hinge getHinge() {
return hinge;
}
public void setHinge(Hinge hinge) {
this.hinge = hinge;
}
/**
* 重写clone方法
*
* @return
* @throws CloneNotSupportedException
*/
@Override
protected PlayChess clone() throws CloneNotSupportedException {
PlayChess playChess = (PlayChess) super.clone();
playChess.hinge = this.hinge.clone();
return playChess;
}
}
之后再次运行就会发现:
这就是深克隆!!!