title: 原型模式
author: rack-leen
avatar: /images/favicon.png
authorDesc: 脱发典范
comments: true
copyright: true
date: 2019-5-19 00:00:00
tags:
Specify the kinds of objects to create using a prototypical instance , and create new objects by copying this prototye.
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建对象。

我们为幼儿园小朋友发成绩表,他们的年龄和成绩都一样,我们只需要改成绩表的名字就行了。
/**
 * 原型模式需要实现Cloneable接口
 */
@Data
@ToString
public class Student implements Cloneable {
    private String name ;
    private String age ;
    private String score ;
    private ArrayList<Student> students = new ArrayList<>();
    private final ArrayList<Student> finalStudent = new ArrayList<>();
    public Student(String name, String age, String score) {
        this.name = name;
        this.age = age;
        this.score = score;
        System.out.println(name + "创建成功");
    }
    /**
     * 这个方法是原型模式的基础
     * @return
     * @throws CloneNotSupportedException
     */
    public Student clone()  {
        System.out.println("学生拷贝成功");
        Student student = null ;
        try {
            // 这是一种浅拷贝,只能拷贝基本类型(包括string),其他的数组这些引用类型就与原型对象共享。
            student =  (Student) super.clone() ;
            // 这个是深拷贝,将数组和引用一起拷贝,每个拷贝的对象有自己的数组和引用
            this.students = (ArrayList<Student>) this.students.clone();
            // 这个finalStudent是由final修饰,,不能重新赋值,不能拷贝
            // this.finalStudent = (ArrayList<Student>) this.finalStudent.clone() ;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return student ;
    }
}
public class Test {
    public static void main(String[] args) {
        Student rack = new Student("rack", "12", "16");
        Student clone = (Student) rack.clone();
        clone.setName("leen");
        System.out.println(rack);
        System.out.println(clone);
    }
}
为原型模式增加一个原型管理器,用来管理原型的创建。
现在我们要创建一个学校,学校里面有教师,学生等实体,我们需要以一个教师和学生作为原型,创建出多个教师和学生。
public interface School extends Cloneable {
    public School clone();
}
@Data
@ToString
public class Student implements School {
    private String name ;
    private String age ;
    private String score ;
    private ArrayList<Student> students = new ArrayList<>();
    private final ArrayList<Student> finalStudent = new ArrayList<>();
    public Student(String name, String age, String score) {
        this.name = name;
        this.age = age;
        this.score = score;
        System.out.println(name + "创建成功");
    }
    /**
     * 这个方法是原型模式的基础
     * @return
     * @throws CloneNotSupportedException
     */
    public Student clone()  {
        System.out.println("学生拷贝成功");
        Student student = null ;
        try {
            // 这是一种浅拷贝,只能拷贝基本类型(包括string),其他的数组这些引用类型就与原型对象共享。
            student =  (Student) super.clone() ;
            // 这个是深拷贝,将数组和引用一起拷贝,每个拷贝的对象有自己的数组和引用
            this.students = (ArrayList<Student>) this.students.clone();
            // 这个finalStudent是由final修饰,,不能重新赋值,不能拷贝
            // this.finalStudent = (ArrayList<Student>) this.finalStudent.clone() ;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return student ;
    }
}
@Data
@ToString
public class Teacher implements School {
    private String name ;
    private String age ;
    private String subject ;
    public Teacher(String name, String age, String subject) {
        this.name = name;
        this.age = age;
        this.subject = subject;
    }
    public Teacher clone(){
        Teacher teacher = null ;
        try {
            teacher = (Teacher) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return teacher ;
    }
}
public class PrototypeManager {
    public Map<String , School> map = new HashMap<>();
    /**
     * 增加除了教师学生之外的学校职位
     * @param key
     * @param value
     */
    public void add(String key , School value){
        this.map.put(key , value);
    }
    /**
     * 从原型池中获取原型,如果原型不存在,抛异常
     * @param key
     * @return
     */
    public School get(String key){
        School school = null;
        try {
            school = this.map.get(key);
        }catch (Exception e){
            e.printStackTrace();
        }
        return school ;
    }
}
public class Test {
    public static void main(String[] args) {
        PrototypeManager prototypeManager = new PrototypeManager();
        prototypeManager.add("teacher" , new Teacher("teacher1" , "21" , "数学"));
        Teacher teacher1 = (Teacher)prototypeManager.get("teacher");
        Teacher teacher2 = teacher1.clone();
        teacher2.setName("teacher2");
        prototypeManager.add("student" , new Student("student1" , "12" , "45"));
        Student student1 = (Student)prototypeManager.get("student");
        Student student2 = student1.clone();
        student2.setName("student2");
        System.out.println(teacher1);
        System.out.println(teacher2);
        System.out.println(student1);
        System.out.println(student2);
    }
}