设计模式(10)——原型模式

文章目录


前言

本系列博客仅是本人在复习中所记录

原型模式

定义:是一种对象型创建模式,通过复制原型实例来创建新的对象。

模式对象

  • 抽象原型类:定义克隆自己的方法的接口
  • 具体原型类:实现具体的克隆业务,并返回一个新的克隆对象
  • 客户类:定义一个原型对象,通过调用该对象的克隆方法来得到更多新的对象。
    在这里插入图片描述

优点

  • 通过已有实例对象,提高新实例对象的创建过程的效率。
  • 动态的增加或减少具体原型类

缺点:克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定容易。特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。

实例说明
场景:创建一个学生对象,对此对象进行克隆。

1、学生对象里不包含对象成员的克隆
Student

/**
 * 具体克隆类
 * 其父类为Object 调用其clone方法
 */
public class Student implements Cloneable {
    private String name;
    private int age;

    public Student(){}
    public Student(String name,int age)
    {
        this.name=name;
        this.age=age;
    }

    /**
     * 普通成员下的克隆
     * @return
     */
    public Object cloneThis()
    {
        Object newObject=null;
        try {
            newObject=super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return newObject;
    }
    public String getName() {
        return name;
    }


    public int getAge() {
        return age;
    }

}

/**
 * 客户类
 */
public class Client {
    public static void main(String[] args) {
        Student s1=new Student("Tom",15);
        Student s2=(Student)s1.cloneThis();

        System.out.println("s1_name:"+s1.getName()+" s1_age:"+s1.getAge());
        System.out.println("s2_name:"+s2.getName()+" s2_age:"+s2.getAge());

        System.out.println("s1==s2?");
        System.out.println(s1==s2);
        /*结果如下:
        s1_name:Tom s1_age:15
		s2_name:Tom s2_age:15
		s1==s2?
		false
        */

    }
}

2、学生对象里包含对象成员的克隆
Student

import java.io.*;

/**
 * 具体克隆类 Student
 */
public class Student implements Cloneable, Serializable {
    private String name;
    private int age;
    private School school;

    public Student(){}

    public Student(String name,int age,School school)
    {
        this.name=name;
        this.age=age;
        this.school=school;
    }

    /**
     * 对象成员下的浅克隆方法
     * @return
     */
    public Object shallowClone() throws CloneNotSupportedException
    {
        Object newObject=null;
        try {
            newObject=super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return newObject;
    }

    /**
     * 对象成员下的深克隆方法
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object newObject=null;
        try
        {
            ByteArrayOutputStream bos=new ByteArrayOutputStream();
            ObjectOutputStream oos=new ObjectOutputStream(bos);
            oos.writeObject(this);
            oos.flush();
            oos.close();


            ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois=new ObjectInputStream(bis);
            newObject=ois.readObject();
            ois.close();

        }catch(Exception e)
        {
            e.printStackTrace();
        }
        return newObject;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public School getSchool() {
        return school;
    }
}

School

import java.io.Serializable;

/**
 * 学校类
 * 作为Student的成员
 */
public class School implements Cloneable, Serializable {
    private String schoolName;
    public School(){}
    public School(String schoolName)
    {
        this.schoolName=schoolName;
    }
    public String getSchoolName()
    {
        return schoolName;
    }
}

浅克隆
Client

/**
 * 测试对象成员下的浅克隆
 */
public class Client {
    public static void main(String[] args) {
        School school=new School("光明中学");
        Student s1=new Student("Mike",18,school);
        Student s2= null;
        try {
            s2 = (Student)s1.shallowClone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        System.out.println("s1_name:"+s1.getName()+" s1_age:"+s1.getAge()+" s1_School"+s1.getSchool().getSchoolName());
        System.out.println("s2_name:"+s2.getName()+" s2_age:"+s2.getAge()+" s2_School"+s2.getSchool().getSchoolName());

        System.out.println("s1==s2?");
        System.out.println(s1==s2);
        System.out.println("s1.school==s2.school?");
        System.out.println(s1.getSchool()==s2.getSchool());
        /**
         * 结果如下:浅克隆对成员对象失败
         *
         * s1_name:Mike s1_age:18 s1_School光明中学
         * s2_name:Mike s2_age:18 s2_School光明中学
         * s1==s2?
         * false
         * s1.school==s2.school?
         * true
         */
    }
}

深克隆

/**
 * 测试对象成员下的深克隆
 */
public class Deep_Client {
    public static void main(String[] args) {
        School school=new School("光明中学");
        Student s1=new Student("Mike",18,school);
        Student s2= null;
        try {
            s2 = (Student)s1.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        System.out.println("s1_name:"+s1.getName()+" s1_age:"+s1.getAge()+" s1_School"+s1.getSchool().getSchoolName());
        System.out.println("s2_name:"+s2.getName()+" s2_age:"+s2.getAge()+" s2_School"+s2.getSchool().getSchoolName());

        System.out.println("s1==s2?");
        System.out.println(s1==s2);
        System.out.println("s1.school==s2.school?");
        System.out.println(s1.getSchool()==s2.getSchool());
        /**
         * 结果如下:对象成员深克隆成功
         *
         * s1_name:Mike s1_age:18 s1_School光明中学
         * s2_name:Mike s2_age:18 s2_School光明中学
         * s1==s2?
         * false
         * s1.school==s2.school?
         * false
         */
    }
}

此外原型模式还有两种扩展写法

  1. 添加原型管理类,定义HashTable类型的集合,使用“键值对”来存储原型对象,客户端可以通过Key来获取对应原型对象的的克隆对象。提供了增加原型对象的方法和获得克隆对象的方法。
    在这里插入图片描述

  2. 相似对象的复制,对原型对象进行克隆以后,仅需要修改对象间的不同点。

参考书籍:
设计模式.刘伟.胡志刚.郭克华.清华大学出版社

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值