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

    参考博文: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

  • 相关阅读:
    HDU 6430 Problem E. TeaTree(虚树)
    hdu6437 Problem L.Videos(网络流)
    Rikka with Prefix Sum(组合数学)
    借教室
    2018年全国多校算法寒假训练营练习比赛(第五场)H Tree Recovery
    1296 营业额统计
    FZU oj Problem 2082 过路费
    大数乘法(适合k进制)
    重载小于号
    莫比乌斯
  • 原文地址:https://www.cnblogs.com/youzoulalala/p/11057425.html
Copyright © 2011-2022 走看看