精华内容
下载资源
问答
  • JAVA原型模式

    千次阅读 2018-09-02 22:38:29
    JAVA原型模式   通过本文将学习到 1、前言 2、原型模式得概念 3、原型的UML图 4、浅克隆于深克隆 5、原型模式的实现 6、原型模式的优缺点 7、原型模式适用场景 8、总结 1、前言 上几篇文章大致讲了工厂...

    JAVA原型模式

     

    通过本文将学习到

    1、前言

    2、原型模式得概念

    3、原型的UML图

    4、浅克隆于深克隆

    5、原型模式的实现

    6、原型模式的优缺点

    7、原型模式适用场景

    8、总结



    1、前言

    上几篇文章大致讲了工厂模式的几种类型,今天聊聊原型模式!今天看了LINUX的发展历史,喜欢他的态度不是为了啥!“just for fun!”觉得好玩,没有什么能比这更重要了!我希望自己打工只是满足自己的生存,同时可以不断向前只是为了做出自己觉得有意思好玩的东西!just for fun!。谈到正题,原型模式也是一种创建型的设计模式。通过复制自己进行创建。分为深度克隆,和浅克隆

    2、原型模式得概念

    原型模式:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象!

    用什么例子来解释原型模式了?

    多重影分身非常合适这个概念,鸣人本体是原型对象!通过“多重影分身术”也就是原型模式(自己本身使用忍术进行创建),进行分身!创建新对象,(分身)。

    需要注意的是,创建新“分身”的人就是鸣人!这个意思就是说原型对象自己不仅是个对象还是个工厂!并且通过克隆方式创建的对象是全新的对象,它们都是有自己的新的地址,通常对克隆模式所产生的新对象(影分身)进行修改(攻击)是不会对原型对象(鸣人)造成任何影响的!,每一个克隆对象都是相对独立的,通过不同的方式对克隆对象进行修改后,可以的到一系列相似但不完全相同的对象。(参考多重影分身之色诱术)。


    3、原型的UML图

    原型模式分三个角色,抽象原型类,具体原型类,客户类。

    抽象原型类(prototype):它是声明克隆方法的接口,是所有具体原型类的公共父类,它可以是接口,抽象类甚至是一个具体的实现类。

    具体原型类(concretePrototype):它实现了抽象原型类中声明的克隆方法,在克隆方法中返回一个自己的克隆对象。

    客户类(Client):在客户类中,使用原型对象只需要通过工厂方式创建或者直接NEW(实例化一个)原型对象,然后通过原型对象的克隆方法就能获得多个相同的对象。由于客户端是针对抽象原型对象编程的所以还可以可以很方便的换成不同类型的原型对象!


    4、浅克隆于深克隆

    在原型模式中有两个概念我们需要了解一下,就是浅克隆和深克隆的概念。按照我的理解,浅克隆只是复制了基础属性,列如八大基本类型,然而引用类型实际上没有复制,只是将对应的引用给复制了!复制地址。

    4.1、浅克隆

    在浅克隆中,如果原型对象的成员变量是值类型(八大基本类型,byte,short,int,long,char,double,float,boolean).那么就直接复制,如果是复杂的类型,(枚举,String,对象)就只复制对应的内存地址

    在换个说法,就是复杂类型的成员变量(String,枚举,啥的)用的是一个。修改了克隆对象的原型对象也会变。他们是共用的。而值类型不是共用的!

     

    4.2、深克隆

    深克隆,我就不用多说了吧,就是什么都是单独的!全部复制,然后各自独立。你修改克隆对象对于原型对象没有丝毫影响,完全的影分身

    5、原型模式的实现

    讲了这么多概念,是时候动动手来实现了!

    创建一个相似或相同的类!

    附件类:
     

    package prototypePattern;
    /**
     * 
    * <p>Title: Attachment</p>  
    * <p>Description:附件类 </p>  
    * @author HAND_WEILI  
    * @date 2018年9月2日
     */
    
    public class Attachment {
     private String name;	//附件名
    
    public String getName() {
    	return name;
    }
    
    public void setName(String name) {
    	this.name = name;
    }
     public void download() {
    	 System.out.println("下载附件"+name);
     }
    }
    

    周报类:这里面很多属性其实可以忽略,但是再真正的操作时他们是确实存在的!

    关键点在于,实现cloneable接口以及用object的clone方法。

    package prototypePattern;
    /**
     * 
    * <p>Title: WeeklyLog</p>  
    * <p>Description:周报类充当具体的原型类 </p>  
    * @author HAND_WEILI  
    * @date 2018年9月2日
     */
    public class WeeklyLog implements Cloneable{
    	
    	private Attachment attachment;
    	private String date;
    	private String name;
    	private String content;
    	public Attachment getAttachment() {
    		return attachment;
    	}
    	public void setAttachment(Attachment attachment) {
    		this.attachment = attachment;
    	}
    	public String getDate() {
    		return date;
    	}
    	public void setDate(String date) {
    		this.date = date;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public String getContent() {
    		return content;
    	}
    	public void setContent(String content) {
    		this.content = content;
    	}
    	//实现clone()方法实现浅克隆
    	public WeeklyLog clone() {
    		//需要实现cloneable的接口,直接继承object就好,它里面自带一个clone方法!
    		Object obj = null;
    		try {
    			obj = super.clone();
    			return (WeeklyLog)obj;
    		} catch (CloneNotSupportedException e) {
    			// TODO Auto-generated catch block
    			System.out.println("不支持克隆方法!");
    			return null;
    		}
    		
    		
    	}
    }
    
    package prototypePattern;                                                                                  
                                                                                                               
    public class Client {                                                                                      
        //测试类,客户端                                                                                              
    	public static void main(String[] args) {                                                               
    		WeeklyLog log_1,log_2;                                                                             
    		log_1 = new WeeklyLog();	//创建原型对象                                                               
    		Attachment attachment = new Attachment(); //创建附件对象                                                 
    		log_1.setAttachment(attachment);	//将附件添加到周报种去                                                   
    		log_2=log_1.clone();	//克隆周报                                                                     
    		System.out.println("周报是否相同"+(log_1==log_2));                                                       
    		System.out.println("附件是否相同"+(log_1.getAttachment()==log_2.getAttachment()));                       
    	}                                                                                                      
    }                                                                                                          
                                                                                                               

    没有实现cloneable接口的结果

    实现了cloneable

    以上是JAVA浅克隆的实现 

    可以看出,周报类型不是相同的类型,但是附件还是同一个类。

    深克隆

    在JAVA怎么做到深度克隆了?通过序列化(Serialization)等方式来进行深度克隆。这个时候要聊一聊什么是序列化了。简单的讲就是序列化就将对象写到流的一个过程,写到流里面去(就是字节流)就等于复制了对象,但是原来的对象并没有动,只是复制将类型通过流的方式进行读取,然后写到另个内存地址中去!

    把原理图画一下好理解,然后开始编程。推荐以为大神的博客。

    JAVA序列化介绍!

    1. 步骤为,首先将引用成员变量序列化。
    2. 将成员变量通过流的方式CLONE
    3. 成功.

    首先将附件类修改。将其序列化

    package prototypePattern;
    
    import java.io.Serializable;
    
    /**
     * 
    * <p>Title: Attachment</p>  
    * <p>Description:附件类 </p>  
    * @author HAND_WEILI  
    * @date 2018年9月2日
     */
    
    public class Attachment_2 implements Serializable {
     private String name;	//附件名
    
    public String getName() {
    	return name;
    }
    
    public void setName(String name) {
    	this.name = name;
    }
     public void download() {
    	 System.out.println("下载附件"+name);
     }
    }
    

    周报类

    package prototypePattern;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.OutputStream;
    import java.io.Serializable;
    
    /**
     * 
    * <p>Title: WeeklyLog</p>  
    * <p>Description:周报类充当具体的原型类 </p>  
    * @author HAND_WEILI  
    * @date 2018年9月2日
     */
    public class WeeklyLog_2 implements Serializable{
    	
    	private Attachment_2 attachment;
    	private String date;
    	private String name;
    	private String content;
    	public Attachment_2 getAttachment() {
    		return attachment;
    	}
    	public void setAttachment(Attachment_2 attachment) {
    		this.attachment = attachment;
    	}
    	public String getDate() {
    		return date;
    	}
    	public void setDate(String date) {
    		this.date = date;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public String getContent() {
    		return content;
    	}
    	public void setContent(String content) {
    		this.content = content;
    	}
    	//通过序列化进行深克隆
    	public WeeklyLog_2 deepclone() throws Exception {
    		//将对象写入流中,
    		ByteArrayOutputStream bao = new ByteArrayOutputStream();
    		ObjectOutputStream oos = new ObjectOutputStream(bao);
    		oos.writeObject(this);
    		//将对象取出来
    		ByteArrayInputStream bi = new ByteArrayInputStream(bao.toByteArray());
    		ObjectInputStream ois = new ObjectInputStream(bi);
    		return (WeeklyLog_2)ois.readObject();
    		
    		
    	}
    }
    

    客户类

    package prototypePattern;                                                                                  
                                                                                                               
    public class Client_2 {                                                                                      
        //测试类,客户端                                                                                              
    	public static void main(String[] args) {                                                               
    		WeeklyLog_2 log_1,log_2=null;                                                                             
    		log_1 = new WeeklyLog_2();	//创建原型对象                                                               
    		Attachment_2 attachment = new Attachment_2(); //创建附件对象                                                 
    		log_1.setAttachment(attachment);	//将附件添加到周报种去                                                   
    		try {
    			log_2=log_1.deepclone();
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}	//克隆周报                                                                     
    		System.out.println("周报对象是否相同"+(log_1==log_2));                                                     
    		System.out.println("附件对象是否相同"+(log_1.getAttachment()==log_2.getAttachment()));                     
    	}                                                                                                      
    }                                                                                                          
                                                                                                               


    6、原型模式的优缺点

    原型模式作为一种快速创建大量相同或相似的对象方式,在软件开发种的应用较为广泛,很多软件提供的CTRL+C和CTRL+V操作的就是原型模式的典型应用!

    优点

    1. 当创建的对象实例较为复杂的时候,使用原型模式可以简化对象的创建过程!
    2. 扩展性好,由于写原型模式的时候使用了抽象原型类,在客户端进行编程的时候可以将具体的原型类通过配置进行读取。
    3. 可以使用深度克隆来保存对象的状态,使用原型模式进行复制。当你需要恢复到某一时刻就直接跳到。比如我们的idea种就有历史版本,或则SVN中也有这样的操作。非常好用!

    缺点

    1. 需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的里面,当对已有的类经行改造时需要修改源代码,违背了开闭原则。
    2. 在实现深克隆的时需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用的时候,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现相对麻烦。

    7、原型模式适用场景

    在以下情况可以考虑使用。

    1创建对象成本比较大,比如初始化要很长时间的,占用太多CPU的,新对象可以通过复制已有的对象获得的,如果是相似的对象,则可以对其成员变量稍作修改。

    2系统要保存对象状态的,而对象的状态改变很小。

    3需要避免使用分层次的工厂类来创建分层次的对象,并且类的对象就只用一个或很少的组合状态!

    8、总结

    创建型的设计模式,除开建造者模式基本学习完毕。不过是基础的学习。还没有正式的运用!在写代码的时候需要取考虑使用这种设计模式与否。学而不用存粹浪费时间。其次,创建型的设计模式是基础,需要好好理解这些模式才能够理解其他的结构型以及行为型的设计模式。

    对于设计模式这一遍是泛读,以后需要通过实战来一一熟悉使用。路漫漫其修远兮吾将上下而求索!

     

    展开全文
  • Java原型模式

    千次阅读 2016-06-01 15:21:03
    Java原型模式  什么是原型模式呢?其实就是使用原型实例指定创建对象的种类,并且通过克隆这些原型创建新的对象。概念十分简单,原型模式的关键点在于克隆(clone)。克隆分为浅度克隆和深度克隆,二者区别在于,...
      Java原型模式
        什么是原型模式呢?其实就是使用原型实例指定创建对象的种类,并且通过克隆这些原型创建新的对象。概念十分简单,原型模式的关键点在于克隆(clone)。克隆分为浅度克隆和深度克隆,二者区别在于,浅度克隆是值类型的基本数据类对象实现完整克隆,但对于引用数据类型的一些对象,它只是克隆源对象的引用地址,即新克隆对象改变时,源对象也会发生改变,这不是我们要的目的。因此,有时,我们更需要深度克隆。
      完成一个完美的克隆是我们关心的重点,以下是完成克隆的方案。
      A、
    Java为我们提供了一个clone()方法,因此我们可以得到克隆方式1:实现Cloneable接口进行克隆
    /* 浅克隆Demo */
    public class ClassCloneDemo implements Cloneable {
    public int i;
    public ClassCloneDemo(int i) {
    this.i = i;
    }
    public static void main(String[] args) throws CloneNotSupportedException {
    ClassCloneDemo ccd = new ClassCloneDemo(1);
    ClassCloneDemo ccd2 = (ClassCloneDemo) ccd.clone();// 浅克隆
    System.out.println("ccd  i: " + ccd.i);
    System.out.println("ccd2 i: " + ccd2.i);
    }
    }
    
    /* 深克隆Demo1 */
    class ClassDeepCloneDemo1 implements Cloneable {
    public A a;
    public ClassDeepCloneDemo1(A a) {
    this.a = a;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
    ClassDeepCloneDemo1 cdcd = null;
    cdcd = (ClassDeepCloneDemo1) super.clone();
    cdcd.a = (A) a.clone();
    return cdcd;
    }
    public static void main(String[] args) throws CloneNotSupportedException {
    ClassDeepCloneDemo1 cdcd = new ClassDeepCloneDemo1(new A(1));
    ClassDeepCloneDemo1 cdcd2 = (ClassDeepCloneDemo1) cdcd.clone();// 深克隆
    // 改变克隆对象里的对象,看源对象里的对象是否变化
    cdcd2.a.i = 2;
    System.out.println("cdcd  i: " + cdcd.a.i);
    System.out.println("cdcd2 i: " + cdcd2.a.i);
    }
    }
    /* 公用测试对象类 */
    class A implements Cloneable, Serializable {
    public int i;
    public A(int i) {
    this.i = i;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
    return super.clone();
    }
    }


      B、使用序列化,将对象通过输入输出流存储取出方式,得到的对象即是一个现成的克隆对象(这样的克隆亦是完整的深度克隆,不存在浅克隆之说了),因此我们我们可以得到克隆方式2:实现Serializable接口进行克隆
    /* 深克隆Demo2 */
    class ClassDeepCloneDemo2 implements Serializable {
    public A a;
    public ClassDeepCloneDemo2(A a) {
    this.a = a;
    }
    public static void main(String[] args) throws CloneNotSupportedException,
    IOException, ClassNotFoundException {
    ClassDeepCloneDemo2 cdcd = new ClassDeepCloneDemo2(new A(1));
    
    /* 深克隆开始 */
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(cdcd);
    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
    ObjectInputStream ois = new ObjectInputStream(bis);
    ClassDeepCloneDemo2 cdcd2 = (ClassDeepCloneDemo2) ois.readObject();
    /* 深克隆结束 */
    
    // 改变克隆对象里的对象,看源对象里的对象是否变化
    cdcd2.a.i = 2;
    System.out.println("cdcd  i: " + cdcd.a.i);
    System.out.println("cdcd2 i: " + cdcd2.a.i);
    }
    }


    展开全文
  • java 原型模式

    2018-09-10 18:29:17
    java 原型模式 代码块(对象) 假如现在有一个对象obj1,对象里有个两个字段(实际场景是有很多字段,然而你需要一个新对象,大部分字段值相同,极个别字段需要更改),你给obj1的name字段赋值为张三、age字段为...

    java 原型模式


    代码块(对象)

    假如现在有一个对象obj1,对象里有个两个字段(实际场景是有很多字段,然而你需要一个新对象,大部分字段值相同,极个别字段需要更改),你给obj1的name字段赋值为张三、age字段为18。然后你又需要一个同样类型的对象obj2,并且还要保证obj2的name字段值为张三、age字段值为18。

    这时候你怎么做?new一个新对象再给字段赋值?,还是说obj2=obj1(这种方式有问题,下面会说到)?

    public class PrototypePattern implements Cloneable{
        private String name;
    
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    
        public PrototypePattern simpleClone () {
            try {
                return (PrototypePattern) this.clone();
            } catch (CloneNotSupportedException e) {
                return null;
            }
        }
    }

    代码块(调用)

    public static void main(String[] args) {
            PrototypePattern obj1 = new PrototypePattern();
            obj1.setName("张三");
            obj1.setAge(18);
            System.out.println("[obj1] name:" + obj1.getName() + ",age:" + obj1.getAge());
            //[obj1] name:张三,age:18
            System.out.println(obj1);
            //test.modle.PrototypePattern@4554617c
    
    
            //使用simpleClone()方法创建的对象是全新的对象,obj3内容更改不会影响到obj1
            PrototypePattern obj3 = obj1.simpleClone();
            System.out.println("[obj3] name:" + obj3.getName() + ",age:" + obj3.getAge());
            //[obj3] name:张三,age:18
            System.out.println(obj3);
            //test.modle.PrototypePattern@74a14482
    
    
            //这种方式最终的引用指向还是obj1,如果obj2内容更改,那么会影响到obj1
            PrototypePattern obj2 = obj1;
            System.out.println("[obj2] name:" + obj2.getName() + ",age:" + obj2.getAge());
            //[obj2] name:张三,age:18
            System.out.println(obj2);
            //test.modle.PrototypePattern@4554617c
            obj2.setAge(38);
            System.out.println("[obj2] name:" + obj2.getName() + ",age:" + obj2.getAge());
            //[obj2] name:张三,age:38
            System.out.println("[obj1] name:" + obj1.getName() + ",age:" + obj1.getAge());
            //[obj1] name:张三,age:38
        }
    展开全文
  • Java 原型模式

    千次阅读 2020-03-29 10:43:08
    文章目录原型模式原型模式Demo使用原型模式的好处浅克隆和深克隆浅克隆深克隆 原型模式 原型模式属于创建型模式,用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象!(但是学姐是不可复制的哦...


    原型模式

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

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

    这就是深克隆!!!

    展开全文
  • JAVA 原型模式

    2020-05-09 23:05:11
    原型模式 文章目录 原型模式 介绍 原型模式的几种实现方式 原型模式(浅拷贝) 原型模式(深拷贝) 介绍 描述 原型模式设计模式属于创建型模式,是用于创建重复的对象,对于当前指定对象创建对象种类,并且...
  • java原型模式

    2020-10-15 14:02:26
    原型模式原型模式的定义定义→简而言之原型模式的实现实现Cloneable接口进行浅拷贝概述具体过程什么是浅拷贝实现Serialization进行深拷贝概述具体过程推荐:序列化什么是深拷贝 原型模式的定义 原型模式属于对象的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,788
精华内容 1,915
关键字:

java原型模式

java 订阅