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

          在这篇博客里面,笔者想要跟大家分享一款比较简单的设计模式-原型模式,说实话刚刚看到这个名字的时候,笔者也很奇怪到底什么才是原型模式呢?是不是提前设计好一个模板,然后按照模板去生产新的对象呢?其实这种理解已经很接近原型模式的定义了,但是在java里面对于这种模式的支持已经很到位了,说白了就是clone,但是这里面还有一些小知识需要注意。

          我们还是先来看看原型模式的准确定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。光这么说大家肯定会觉得很抽象,下面就让我们来看个具体的例子吧!话说很久很久以前还没有人,只有神的时候,一天女蜗娘娘突然有个想法:要不就造些人来玩玩。于是乎,我们炎黄华夏名族就诞生了,在以后的几千年的岁月里,繁荣发展。那么如果用原型模式来描述这个场景,该如何实现呢?首先我们需要定义出一个女蜗类,代码如下:

    public class NvWo {
    	public People makePeople() {
    		return new People();
    	}
    }
    

      在女娲娘娘造出一批又一批人之后,我们人类就开始学会了自我繁殖后代。每一个子女都会从父母那里遗传DNA,既有父母的模样,但是还会有一定的差异。这个时候,如果我们想要准确模拟这个相似性,以及差异性的话,让我们来看看People类的实现:

    public class People implements Cloneable {
    	@Override
    	protected People clone() throws CloneNotSupportedException {
    		People people=null;
    		people=(People)super.clone();
    		return people;
    	}
    }
    

      上面的代码很简单,笔者只是实现了Cloneable接口让People实现自我繁殖。下面让我们再来进一步思考,每个人都会有自己特有的一些属性吧!比如性别、年龄、出生年月等,下面我们先来建一个实体类模拟出这些属性,代码如下:

    public class PeopleInfo {
    
    	public String Sex;
    	public int Age;
    	public Date birday;
    }
    

      好了,属性特征定义出来了,怎么嵌入到每个人里面呢?通过构造函数嵌入吗?这里就有一个很关键的知识点:当我们进行clone操作的时候,构造函数是不会执行的,因为clone操作是从内存中以二进制流的方式进行拷贝的。比如下面的代码:

    public class People implements Cloneable {
    	private PeopleInfo peopleInfo=null;
    	
    	public People(){
    		peopleInfo=new PeopleInfo();
    	}
    	
    	@Override
    	protected People clone() throws CloneNotSupportedException {
    		People people=null;
    		people=(People)super.clone();
    		return people;
    	}
    }
    

      同时上面代码还有一个致命的问题,就是当我们调用People类里面的Clone方法之后,People类里面peopleInfo变量对象有没有被拷贝呢?答案是否定的,因为上面代码我们实现的只是一种浅拷贝,调用的只是Object对象里面的Clone方法。这就牵涉到浅拷贝和深拷贝的区别问题,当我们实现浅拷贝的时候,里面的非基本类型变量是不会被拷贝的。而深拷贝呢?让我们来改造一下上面的代码,让其实现深拷贝:

    public class People implements Cloneable {
    	private PeopleInfo peopleInfo;
    	
    	@Override
    	protected People clone() throws CloneNotSupportedException {
    		People people=null;
    		people=(People)super.clone();
    		this.peopleInfo=(PeopleInfo)this.peopleInfo.clone();
    		return people;
    	}
    }
    
    public class PeopleInfo implements Cloneable {
    
    	public String Sex;
    	public int Age;
    	public Date birday;
    	@Override
    	protected PeopleInfo clone() throws CloneNotSupportedException {
    		PeopleInfo peopleInfo=(PeopleInfo)super.clone();
    		return peopleInfo;
    	}
    }
    

      通过上面的代码,你会发现当我们clone一个People对象之后,修改PeopleInfo属性就不会影响其他People了,因为它们都是各自独立的。最后我们再来看看原型模式的优点,一个是性能良好:因为原型模式是通过clone,而clone又是通过内存二进制流拷贝的,所以相较于new对象性能好很多;另一个就是能够逃避构造函数约束:前面我们也提过clone的时候,构造函数是不执行的。

          好了,今天的博客就到这里,see you!

  • 相关阅读:
    Redis
    Redis
    Redis
    linux 安装docker
    linux 安装nexus
    linux 安装jenkins
    linux 安装gitlab
    python 类的继承
    python raise & assert
    python super()
  • 原文地址:https://www.cnblogs.com/xiaocai20091687/p/xiaocai_design_nine.html
Copyright © 2011-2022 走看看