使用场景可用于飞机大战复制敌机

传统方式解决克隆羊问题

代码演示

需要复制的Sheep类

复制代码
package com.wang.prototype;

public class Sheep {
    private String name;
    private int age;
    private String color;
    public Sheep(String name, int age, String color) {
        super();
        this.name = name;
        this.age = age;
        this.color = color;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    @Override
    public String toString() {
        return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]";
    }
    
    
}
复制代码

  需要使用复制类的客户端

复制代码
package com.wang.prototype;

public class Client {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Sheep sheep = new Sheep("tom", 1, "白色");
        
        Sheep sheep2 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep3 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep4 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep5 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        //....
        
        System.out.println(sheep);
        System.out.println(sheep2);
        System.out.println(sheep3);
        System.out.println(sheep4);
        System.out.println(sheep5);
        //...
    }

}
复制代码

传统的方式的优缺点

1) 优点是比较好理解,简单易操作。

2) 在创建新的对象时,总是需要重新获取原始对象的属性,如果创建的对象比较复杂 时,效率较低

3) 总是需要重新初始化对象,而不是动态地获得对象运行时的状态, 不够灵活

4) 改进的思路分析 思路:Java中Object类是所有类的根类,Object类提供了一个clone()方法,该方法可以 将一个Java对象复制一份,但是需要实现clone的Java类必须要实现一个接口Cloneable, 该接口表示该类能够复制且具有复制的能力 => 原型模式

 

原型模式

基本介绍

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

2) 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象, 无需知道如何创建的细节

3) 工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建 的对象通过请求原型对象拷贝它们自己来实施创建,即 对象.clone()

4) 形象的理解:孙大圣拔出猴毛, 变出其它孙大圣

 

 

原理结构图说明 1)

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

2) ConcretePrototype: 具体的原型类, 实现一个克隆自己的操作

3) Client: 让一个原型对象克隆自己,从而创建一个新的对象(属性一样)

 

原型模式解决克隆羊问题的应用实例

使用原型模式改进传统方式,让程序具有更高的效率和扩展性。

代码演示:

原型类Sheep实现Cloneable接口,重写clone方法

复制代码
package com.wang.prototype.improve;

public class Sheep implements Cloneable{
    private String name;
    private int age;
    private String color;
    private String address="蒙古";
    public Sheep(String name, int age, String color) {
        super();
        this.name = name;
        this.age = age;
        this.color = color;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {

        Sheep sheep=null;

        sheep= (Sheep) super.clone();

        return sheep;
    }


    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", color='" + color + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
复制代码
Client让一个原型对象克隆自己
复制代码
package com.wang.prototype.improve;

import com.wang.prototype.improve.Sheep;
public class Client {

    public static void main(String[] args) throws CloneNotSupportedException {
        // TODO Auto-generated method stub

        Sheep sheep = new Sheep("tom", 1, "白色");
        Sheep sheep1 = (Sheep) sheep.clone();
        Sheep sheep2 = (Sheep) sheep.clone();
        Sheep sheep3 = (Sheep) sheep.clone();
        Sheep sheep4 = (Sheep) sheep.clone();
        Sheep sheep5 = (Sheep) sheep.clone();


        System.out.println(sheep);
        System.out.println(sheep1);
        System.out.println(sheep2);
        System.out.println(sheep3);
        System.out.println(sheep4);
        System.out.println(sheep5);
        //...
    }

}
复制代码

原型模式在Spring框架中源码分析

Spring中原型bean的创建,就是原型模式的应用

 

<bean id="id01" class="com.atguigu.spring.bean.Monster" scope="prototype"/>

Test.java

ApplicationContext applicationContext = new 
ClassPathXmlApplicationContext("beans.xml");
//获取monster[通过id获取monster]
Object bean = applicationContext.getBean("id01");
System.out.println("bean" + bean);

 

 

 

深入讨论-浅拷贝和深拷贝

浅拷贝的介绍

1) 对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将 该属性值复制一份给新的对象。

2) 对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类 的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内 存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个 实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成 员变量值

3) 前面我们克隆羊就是浅拷贝

4) 浅拷贝是使用默认的 clone()方法来实现 sheep = (Sheep) super.clone();

 

深拷贝基本介绍

1) 复制对象的所有基本数据类型的成员变量值

2) 为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变 量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对 整个对象进行拷贝

3) 深拷贝实现方式1:重写clone方法来实现深拷贝

4) 深拷贝实现方式2:通过对象序列化实现深拷贝(推荐)

 

深拷贝应用实例

1) 使用 重写clone方法实现深拷贝

需要单独clone的深拷贝引用对象

复制代码
package com.wang.prototype.deepclone;
import java.io.Serializable;

public class DeepCloneableTarget implements Serializable, Cloneable {


    private static final long serialVersionUID = 1L;

    private String cloneName;

    private String cloneClass;

    //构造器
    public DeepCloneableTarget(String cloneName, String cloneClass) {
        this.cloneName = cloneName;
        this.cloneClass = cloneClass;
    }

    //因为该类的属性,都是String , 因此我们这里使用默认的clone完成即可
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "DeepCloneableTarget{" +
                "cloneName='" + cloneName + '\'' +
                ", cloneClass='" + cloneClass + '\'' +
                '}';
    }
}
复制代码

原型对象DeepProtoType(包含引用对象)

复制代码
package com.wang.prototype.deepclone;

import java.io.Serializable;

public class DeepProtoType implements Serializable,Cloneable {

    public String name; //String 属性
    public DeepCloneableTarget deepCloneableTarget;// 引用类型
    public DeepProtoType() {
        super();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object deep=null;
        deep=super.clone();//全部对象clone
        DeepProtoType deepProtoType= (DeepProtoType) deep;
        deepCloneableTarget = (DeepCloneableTarget) deepCloneableTarget.clone();//对引用对象单独clone
        return deepProtoType;
    }
}
复制代码

实现克隆

复制代码
package com.wang.prototype.deepclone;

import com.wang.prototype.improve.Sheep;

public class Client {

    public static void main(String[] args) throws CloneNotSupportedException {
        DeepProtoType p = new DeepProtoType();
        p.name = "宋江";
        p.deepCloneableTarget = new DeepCloneableTarget("大牛", "小牛");

        DeepProtoType p2 = (DeepProtoType) p.clone();
        System.out.println("p.name"+p.name+",p.deepCloneableTarget"+p.deepCloneableTarget.hashCode());
        System.out.println("p2.name"+p.name+",p2.deepCloneableTarget"+p2.deepCloneableTarget.hashCode());


    }
}
复制代码

结果

 

 引用对象不是同一个了 实现了引用对象clone

 

 

2) 使用序列化来实现深拷贝

3) 代码演示

复制代码
package com.wang.prototype.deepclone;

import java.io.*;

public class DeepProtoType implements Serializable,Cloneable {

    public String name; //String 属性
    public DeepCloneableTarget deepCloneableTarget;// 引用类型
    public DeepProtoType() {
        super();
    }
public Object deepClone() throws ClassNotFoundException, IOException {
        ByteArrayOutputStream bos=null;
        ObjectOutputStream oos=null;
        ByteArrayInputStream bis=null;
        ObjectInputStream ois=null;


        try {
            bos=new ByteArrayOutputStream();
            oos=new ObjectOutputStream(bos);
            oos.writeObject(this);
            bis=new ByteArrayInputStream(bos.toByteArray());
            ois=new ObjectInputStream(bis);
            DeepProtoType copyObj=(DeepProtoType)ois.readObject();
            return copyObj;

        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }finally {
            ois.close();
            bis.close();
            oos.close();
            bos.close();



        }


    }
}
复制代码

 

原型模式的注意事项和细节

 1) 创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提 高效率

2) 不用重新初始化对象,而是动态地获得对象运行时的状态

3) 如果原始对象发生变化(增加或者减少属性),其它克隆对象的也会发生相应的变化, 无需修改代码

4) 在实现深克隆的时候可能需要比较复杂的代码

5) 缺点:需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有 的类进行改造时,需要修改其源代码,违背了ocp原则

 

posted on   upupup-999  阅读(53)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!



点击右上角即可分享
微信分享提示