设计模式之原型模式

参考博文:https://www.cnblogs.com/java-my-life/archive/2012/04/11/2439387.html  用于自身学习,侵权必删。

2019-06-20  10:28:14

原型模式  Prototype

什么是原型模式:同样用于解决new对象的问题,类似于工厂模式中抽象产品和抽象工厂的合并。要求对象实现“克隆”自身的接口,通过复制对象本身来创建一个新的实例。

适用性:处理某些“结构复杂的对象”(某一复杂状态的对象)的创建工作。

原型模式的角色:

  (1)Client:客户类提出创建对象的请求。

  (2)Prototype:这是一个抽象角色,通常由一个Java接口或Java抽象类实现。此角色给出所有的具体原型类所需的接口。

  (3)Concrete Prototype:被复制的对象。此角色需要实现抽象的原型角色所要求的接口。

基本类图:

 

克隆的两种概念:

浅克隆:只负责克隆按值传递的数据(比如基本数据类型、String类型),而不复制它所引用的对象,换言之,所有的对其他对象的引用都仍然指向原来的对象。

深克隆:除了浅度克隆要克隆的值外,还负责克隆引用类型的数据。

两种克隆的实现方式:

1 浅克隆:实现Cloneable接口,调用Object对象的clone()方法,返回的便是浅克隆对象。

  protected Object clone() throws CloneNotSupportedException

  创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。这样做的目的是,对于任何对象 x,表达式:x.clone() != x为 true,

表达式:x.clone().getClass() == x.getClass()也为 true
但这些并非必须要满足的要求。一般情况下:x.clone().equals(x)为 true,但这并非必须要满足的要求。


2 深克隆:把对象写到流里的过程是序列化(Serialization)过程;而把对象从流中读出来的过程则叫反序列化(Deserialization)过程。
应当指出的是,写到流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。
序列化基本代码如下:
    public  Object deepClone() throws IOException, ClassNotFoundException{
        //将对象写到流里
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        //从流里读回来
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
    }

原型模式基本代码:

参看文首博文。

import java.io.*;

public class Monkey implements Cloneable,Serializable{
    public int age;
    public GoldRingedStaff staff;

    public Monkey(int age, GoldRingedStaff staff) {
        this.age = age;
        this.staff = staff;
    }

    public Monkey() {
    }

    //重写super.clone(),返回Mokey对象
    @Override
    protected Monkey clone() throws CloneNotSupportedException {
        return (Monkey)super.clone();
    }

    //深克隆
    public Monkey deepClone(){
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (Monkey)ois.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
            System.out.println("deep clone failed.");
            return null;
    }
}

 

 

import java.io.Serializable;

public class GoldRingedStaff implements Serializable {
    private float height = 100.0f;
    private float diameter = 10.0f;
    /**
     * 增长行为,每次调用长度和半径增加一倍
     */
    public void grow(){
        this.diameter *= 2;
        this.height *= 2;
    }
    /**
     * 缩小行为,每次调用长度和半径减少一半
     */
    public void shrink(){
        this.diameter /= 2;
        this.height /= 2;
    }
}

 

 

public class TheGreatestSage {
    private Monkey monkey = new Monkey(10,new GoldRingedStaff());

    public void change(){
        try {
            Monkey copyMonkey = monkey.clone();//浅克隆
            System.out.println("大圣本尊跟克隆的年龄是否相同 " + (monkey.age == copyMonkey.age));
            System.out.println("大圣本尊跟克隆的大圣是否为同一个对象 " + (monkey == copyMonkey));
            System.out.println("大圣本尊持有的金箍棒 跟 克隆的大圣持有的金箍棒是否为同一个对象" + (monkey.staff == copyMonkey.staff));

        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            System.out.println("clone failed");
        }
    }

    public void deepChange(){
        Monkey copyMonkey = monkey.deepClone();
        System.out.println("大圣本尊跟克隆的年龄是否相同 " + (monkey.age == copyMonkey.age));
        System.out.println("大圣本尊跟克隆的大圣是否为同一个对象 " + (monkey == copyMonkey));
        System.out.println("大圣本尊持有的金箍棒 跟 克隆的大圣持有的金箍棒是否为同一个对象" + (monkey.staff == copyMonkey.staff));
    }

    public static void main(String[] args) {
        TheGreatestSage sage = new TheGreatestSage();
        sage.change();
        System.out.println("========================");
        sage.deepChange();
    }

}

 

 

//输出结果
大圣本尊跟克隆的年龄是否相同 true
大圣本尊跟克隆的大圣是否为同一个对象 false
大圣本尊持有的金箍棒 跟 克隆的大圣持有的金箍棒是否为同一个对象true
========================
大圣本尊跟克隆的年龄是否相同 true
大圣本尊跟克隆的大圣是否为同一个对象 false
大圣本尊持有的金箍棒 跟 克隆的大圣持有的金箍棒是否为同一个对象false

 

posted @ 2019-06-20 10:55  由走啦啦啦  阅读(138)  评论(0编辑  收藏  举报