Java 原型模式-学姐最终还是被我征服了......让你以最生动的例子记住原型模式


原型模式

原型模式属于创建型模式,用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象!(但是学姐是不可复制的哦,只有我这里有,还不赶快关注我的 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;
    }

}


之后再次运行就会发现:
在这里插入图片描述

这就是深克隆!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章