读前辈的大话设计模式(七)之原型模式,抒自己的读后感

    原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

    原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节。克隆模式对性能有很大的提高,因为每次创建对象的时候,如果我们都是通过new来完成,那么每次都要执行一次构造函数,如果构造函数的执行时间很长,则多次执行这个初始化就显得很低效。一般在初始化的信息不发生变化的情况下,克隆是最好的办法,这既能隐藏对象创建的细节,又对性能有很大的提高。等于是不用重新初始化对象,而是动态地获得对象运行时的状态。

    原型模式结构:

    Prototype:抽象类,原型类,声明一个克隆自身的接口,

    Client:关联原型类 Prototype,让一个原型克隆自身,从而创建一个行的对象,

    ConcretePrototype:具体原型类,继承抽象的原型类,实现一个克隆自身的操作。

    写这篇文章让我对Java和c#的差别又加深了些,因为在写的过程中有些细节需要对比查资料,还好最后搞定了,主要是我也是在学习的阶段。也许会有人笑话这样也来写文章,但我并不觉得羞愧,因为我早说过了,这是自己的读后感,想到就表达出来。所以很欢迎大神指点其中的不足。

    看完书中这一篇之后发现,原型模式核心的内容是 clone() 方法的重写。

    这里面涉及到两个核心的概念:浅复制 深复制  ,这两种表现出来的结果状态略有不同,关于这个的详细解释,请看这篇文章 详解Java中的clone方法 -- 原型模式,本文按照书中介绍,分别演示浅复制和深复制的效果。嗯,说了好多了。我们直接试试代码。

    先来浅复制的实现:

    1、新建一个原型类,这是个抽象类:

package abstractprototype;

/**
 * Created by Administrator on 2017/8/4.
 */

/**
 * Prototype 实现Cloneable接口,重写接口中的clone()方法
 */
public abstract class Prototype implements Cloneable{

    @Override
    public Prototype clone() throws CloneNotSupportedException{
        return (Prototype)super.clone();
    }
}

    2、新建一个具体原型类,继承原型类这个抽象类:

package concreteprototype;

import abstractprototype.Prototype;
import lombok.Getter;
import lombok.Setter;

/**
 * Created by Administrator on 2017/8/4.
 */
@Getter
@Setter
public class ConcretePrototype extends Prototype implements Cloneable{

    private String name;

    /**
     * 性别
     */
    private String gender;

    private int age;

    /**
     * 引用‘工作经历’对象
     */
    private WorkExperience workExperience;

    /**
     * 在具体原型类实例化的同时,实例化‘工作经历’
     * @param name
     */
    public ConcretePrototype(String name) {
        this.name = name;
        workExperience = new WorkExperience();
    }

    /**
     * s设置基本信息
     * @param gender
     * @param age
     */
    public void  setBasicInfo(String gender,int age){
        this.gender = gender;
        this.age = age;

    }

    /**
     * 设置工作经历
     * @param workTime
     * @param company
     */
    public void setWorkExp(String workTime,String company){
            workExperience.setWorkDate(workTime);
            workExperience.setCompany(company);
    }

    /**
     * 效果展示
     */
    public void display(){
        System.out.println(name + " " + gender + " " + age);
        System.out.println(workExperience.getWorkDate() + " " + workExperience.getCompany());
    }

    @Override
    public Prototype clone() throws CloneNotSupportedException{

       return super.clone();
    }
}


    3、新建工作经历类:

package concreteprototype;

import abstractprototype.Prototype;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

/**
 * Created by Administrator on 2017/8/4.
 */
@NoArgsConstructor
@Getter
@Setter
public class WorkExperience{

    private String workDate;
    private String company;

}

    4、新建测试类:

import concreteprototype.ConcretePrototype;
import org.junit.Test;

/**
 * Created by Administrator on 2017/8/4.
 */
public class TestPrototype {

    @Test
    public void testPrototype() throws CloneNotSupportedException {

        ConcretePrototype personNumberA = new ConcretePrototype("赛赛");
        personNumberA.setWorkExp("1990-1995","ABC");
        personNumberA.setBasicInfo( "男",20);

        //开始复制
        ConcretePrototype personNumberB = (ConcretePrototype) personNumberA.clone();
        //更改工作经历
        personNumberB.setWorkExp("2000-2005","SUN Java");
        personNumberB.setBasicInfo( "女",22);

        personNumberA.display();
        System.out.println("------------------------------------------");
        personNumberB.display();

    }
}

    执行效果如下所示:


    结果分析:浅复制效果明显有瑕疵,因为两次工作经历都变成了最后一次设置的值,不是我们想要的结果,


    接下来是深复制的实现:

    1、修改 ‘’工作经历’' 这个类,继承原型类这个抽象类,重写clone()方法:

package concreteprototype;

import abstractprototype.Prototype;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

/**
 * Created by Administrator on 2017/8/4.
 */
@NoArgsConstructor
@Getter
@Setter
public class WorkExperience extends Prototype{

    private String workDate;
    private String company;

    @Override
    public Prototype clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

    2、修改具体原型类:提供一个私有构造器,参数类型为 “工作经历类” ;修改clone()方法,具体做法是调用私有的构造器,让工作经历 clone 完成,然后再给这个具体原型类

的对象的相关属性赋值,最后返回一个深复制的具体原型类对象。修改后的类如下:

package concreteprototype;

import abstractprototype.Prototype;
import lombok.Getter;
import lombok.Setter;

/**
 * Created by Administrator on 2017/8/4.
 */
@Getter
@Setter
public class ConcretePrototype extends Prototype implements Cloneable{

    private String name;

    /**
     * 性别
     */
    private String gender;

    private int age;

    /**
     * 引用‘工作经历’对象
     */
    private WorkExperience workExperience;

    /**
     * 在具体原型类实例化的同时,实例化‘工作经历’
     * @param name
     */
    public ConcretePrototype(String name) {
        this.name = name;
        workExperience = new WorkExperience();
    }

    private ConcretePrototype(WorkExperience workExp){
        try {
            this.workExperience = (WorkExperience) workExp.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

    }

    /**
     * s设置基本信息
     * @param gender
     * @param age
     */
    public void  setBasicInfo(String gender,int age){
        this.gender = gender;
        this.age = age;

    }

    /**
     * 设置工作经历
     * @param workTime
     * @param company
     */
    public void setWorkExp(String workTime,String company){
            workExperience.setWorkDate(workTime);
            workExperience.setCompany(company);
    }

    /**
     * 效果展示
     */
    public void display(){
        System.out.println(name + " " + gender + " " + age);
        System.out.println(workExperience.getWorkDate() + " " + workExperience.getCompany());
    }

    /**
     * 调用私有的构造器,让工作经历 clone 完成,然后再给这个具体原型类的对象的相关属性赋值,
     * 最后返回一个深复制的具体原型类对象
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    public Prototype clone() throws CloneNotSupportedException{
        
        ConcretePrototype concretePrototype = new ConcretePrototype(this.workExperience);
        concretePrototype.name = this.name;
        concretePrototype.gender = this.gender;
        concretePrototype.age = this.age;

        return concretePrototype;
    }
}

    3、测试类保持不变。

    执行结果如下所示:


    嗯,总结在前面以及文中引用的那篇文章总结的很清晰了,到此原型模式基本介绍结束了。


猜你喜欢

转载自blog.csdn.net/medier/article/details/76651652
今日推荐