zoukankan      html  css  js  c++  java
  • 原型模式

    设计模式

    原型模式

    定义:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的对象。

    特点:

    ​ 1、简化对象创建的流程,同时也可以提高效率

    ​ 2、如果原始对象发生变化,其克隆对象也会发生相应变化,无需修改代码

    劣势:

    ​ 1、每个对象都需要配备一个克隆方法,违反OCP(开闭)原则

    原型模式的拷贝分为浅拷贝深拷贝

    浅拷贝
    对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递
    对于数据类型是引用数据类型的成员变量,那么浅拷贝会进行引用传递
    

    以打印简历为例:

    package com.prototype;
    
    public class Resume implements Cloneable{
        private String name;
        private boolean sex;
        private String salary;
     	private Witness witness;//见证人
        /*
           简历类
           
           浅拷贝:
           1. 实现Cloneable接口
           2. 重写clone()方法
        */
        //略写有参无参构造方法,set、get方法 
        
        //重写clone方法
    	protected Object clone() throws CloneNotSupportedException {
    		System.out.println("复制简历成功!!");
    		Resume clone = (Resume) super.clone();
    		return clone;
    	}
    
    	@Override
    	public String toString() {
    		return "Resume [name=" + name + ", sex=" + sex + ", salary=" + salary
    				+ "]";
    	}
    	  
    }
    
    
    package com.prototype;
    //客户端
    public class Client {
       public static void main(String[] args) {
    	  Resume resume = new Resume("jack", true, "面试");
    	  resume.setWitness(new Witness("mary", "经理"));
    	  //打印2份简历
    	  for (int i = 0; i < 2; i++) {
    		try {
    			Resume clone = (Resume) resume.clone();
    			System.out.println("打印简历:"+clone);
    			System.out.println("resume的哈希值"+clone.hashCode());
    			System.out.println("witness的哈希值"+clone.getWitness().hashCode());
    		} catch (CloneNotSupportedException e) {
    			e.printStackTrace();
    		}
    		}
       }
    }
    
    
    package com.prototype;
    //见证人 类
    public class Witness{
       private String name;//姓名
       private String job;//职位
       
    //略写有参无参构造方法,set、get方法
        
    @Override
    public String toString() {
    	return "Witness [name=" + name + ", job=" + job + "]";
    }
       
    }
    
    
    显示:
    复制简历成功!!
    打印简历:Resume [name=jack, sex=true, salary=面试, witness=Witness [name=mary, job=经理]]
    resume的哈希值1167165921
    witness的哈希值1442002549
    
    复制简历成功!!
    打印简历:Resume [name=jack, sex=true, salary=面试, witness=Witness [name=mary, job=经理]]
    resume的哈希值1383884648
    witness的哈希值1442002549
    
    结果:resume克隆对象的内容一样,但不是同一个对象,其中属性witness进行的是引用传递
    
    深拷贝:

    实现方式1:重写clone()方法(不推荐)

    缺点:虽然层次调用clone方法可以实现深拷贝,但是显然代码量实在太大。特别对于属性数量比较多、层次比较深的类而言,每个类都要重写clone方法太过繁琐。

    也是以打印简历为例:

    package com.prototype;
    
    public class Resume2 implements Cloneable{
        //简历2.0版本
    	private String name;
    	private int age;
    	private String salary;
    	private Witness witness;
    	
    	//略写有参无参构造方法,set、get方法
    
    	@Override
    	protected Object clone() throws CloneNotSupportedException {
            /*
             * 完成深拷贝
             * 实现方式1:重写clone()方法
             * */
            //第一步:完成对基本数据类型或String类型的拷贝
    		Resume2 resume2 = (Resume2)super.clone();
    		//第二步:对引用类型进行处理(引用类型也要实现Cloneable接口,重写clone方法)
    		resume2.witness = (Witness) witness.clone();
    		
    		return resume2;
    	}
    }
    
    
       package com.prototype;
       //见证人 类
       public class Witness implements Cloneable{
       private String name;
       private String job;
        
    	//略写有参无参构造方法,set、get方法 ,toString方法  
        
    	@Override
    	protected Object clone() throws CloneNotSupportedException {
    		return (Witness)super.clone();
    	}
    
        @Override
        public String toString() {
            return "Witness [name=" + name + ", job=" + job + "]";
        }
       
    }
    
    
    package com.prototype;
    
    public class Client2 {
       public static void main(String[] args) {
    	 Resume2 resume2 = new Resume2("jack", 20, "面议");
    	 resume2.setWitness(new Witness("mary", "经理"));
    	 
    	 for (int i = 0; i < 2; i++) {
    		try {
    			Resume2 clone1 = (Resume2) resume2.clone();
    			System.out.println("打印简历:"+clone1);
    			System.out.println("clone1的哈希值:"+clone1.hashCode());
    			System.out.println("witness的哈希值:"+clone1.getWitness().hashCode());
    		} catch (CloneNotSupportedException e) {
    			e.printStackTrace();
    		}
    	}
       }
    }
    
    
    显示:
    打印简历:Resume2 [name=jack, age=20, salary=面议, witness=Witness [name=mary, job=经理]]
    clone1的哈希值:1167165921
    witness的哈希值:1442002549
    
    打印简历:Resume2 [name=jack, age=20, salary=面议, witness=Witness [name=mary, job=经理]]
    clone1的哈希值:1383884648
    

    实现方式2:通过对象序列化(推荐)

    特点:一步到位不管类的结构和如何复杂,整体处理

    注意:如果某个属性被transient修饰,那么该属性就无法被拷贝了

    步骤:1.要进行拷贝的类要实现Serializable接口 2.进行序列化与反序列化

    package com.prototype;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    
    public class Resume3 implements Serializable{
        //简历 3.0版本
    	private String name;
    	private int age;
    	private String salary;
    	private Witness witness;//Witness类也要实现Serializable接口
    	
    	//set get方法,有参无参构造函数略写
    
        //对象序列化与反序列化
    	public Resume3 deepClone(){
    		ByteArrayOutputStream bos = null;
    		ByteArrayInputStream bis = null;
    		ObjectOutputStream oos = null;
    		ObjectInputStream ois = null;
    		Resume3 resume3 = null;
    		try {
    			//对象序列化
    			bos = new ByteArrayOutputStream();
    			oos = new ObjectOutputStream(bos);
    			oos.writeObject(this);
    			//反序列化
    			bis = new ByteArrayInputStream(bos.toByteArray());
    			ois = new ObjectInputStream(bis);
    			resume3 = ois.readObject();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		}finally{
    			try {
    				//关闭流
    				bos.close();
    				oos.close();
    				bis.close();
    				ois.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			
    		}
    		
    		return resume3;
    	}
    	@Override
    	public String toString() {
    		return "Resume3 [name=" + name + ", age=" + age + ", salary=" + salary
    				+ ", witness=" + witness + "]";
    	}
    	
    }
    
    
    package com.prototype;
    
    import java.io.Serializable;
    
    public class Witness implements Serializable{
       private String name;
       private String job;
        
    //略写set get toString方法
       
    }
    
    
    package com.prototype;
    //客户端
    public class Client3 {
       public static void main(String[] args) {
    	  Resume3 resume3 = new Resume3("jack", 20, "面议");
    	  resume3.setWitness(new Witness("mary", "经理"));
    	  Resume3 d1 =  resume3.deepClone();
    	  Resume3 d2 =  resume3.deepClone();
    	  System.out.println(d1);
    	  System.out.println(d2);
    	  System.out.println(d1.hashCode()+"   "+d2.hashCode());
    	  System.out.println(d1.getWitness().hashCode()+" "+d2.getWitness().hashCode());
       }
    }
    
    
    显示:
    Resume3 [name=jack, age=20, salary=面议, witness=Witness [name=mary, job=经理]]
    Resume3 [name=jack, age=20, salary=面议, witness=Witness [name=mary, job=经理]]
    1932154105   1613816448
    694579926  83711190
    
  • 相关阅读:
    C# 3.0特性
    C# 4.0特性
    Mvc系统学习9——Areas学习
    MVC系统学习8——AsyncController
    MVC系统学习7—Action的选择过程
    MVC系统学习6—Filter
    MVC系统学习5——验证
    对象排序
    Spring上下文信息获取简单实现
    设计模式
  • 原文地址:https://www.cnblogs.com/wwww2/p/14629417.html
Copyright © 2011-2022 走看看