Java设计模式创建型模式--原型模式(prototype)

原型模式

1. 什么是原型模式:

用原型实例指定创建对象种类,并且通过拷贝这些原型创建新的对象。是一种创建型设计模式,允许一个对象再创建另外一个可定制对象,无需知道创建的细节。

2.为什么要用原型模式:
复制类时可以简单操作,而无需在代码中直接冗余的创建,让程序有更高的效率和扩展性。

3.原型模式适用于什么地方:

  • 当一个系统应该独立于他的产品创建,构成和表示时。
  • 要实例化的类是在运行时指定
  • 为了避免一个与产品类层次平行的工厂类层次时
  • 当一个类实例只能有几个不同状态组合的一种时。

在这里插入图片描述**原型模式实现方法:**在类中实现clone方法,给使用者提供clone接口。

一、浅拷贝复制:

  1. 对于数据类型为基本数据类型,浅拷贝会直接进行值传递,就是将该属性值复制给新的对象。
  2. 对于引用数据类型,浅拷贝会进行引用传递,也就是将该对象的引用值赋给新的对象,则新对象与被拷贝的对象的成员变量都指向一个实例,对原被拷贝的变量实例的值的改变也会影响新对象中的变量。

实现:

  1. 实现Cloneable接口,重写clone方法。

原型类:

class DoriSheep implements Cloneable {
    private String name ;
    private  int age ;
    public DoriSheep sheep;


    @Override
    protected Object clone() throws CloneNotSupportedException {
        DoriSheep sheep =null;
        try {
            sheep = (DoriSheep) super.clone();
        }catch (Exception e){
            System.out.println("chucuole ");
        }
        return  sheep;
    }

    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 DoriSheep getSheep() {
        return sheep;
    }

    public void setSheep(DoriSheep sheep) {
        this.sheep = sheep;
    }

    @Override
    public String toString() {
        return "DoriSheep{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sheep=" + sheep +
                '}';
    }
}

测试类:

public class PrototypeFirstTest {

    public static void main(String[] args) {
        DoriSheep sheep = new DoriSheep();
        sheep.setName("Dori");
        sheep.setAge(20);
        DoriSheep Fieldsheep = new DoriSheep();
        sheep.setSheep(Fieldsheep);

        try {
            DoriSheep sheep1 = (DoriSheep) sheep.clone();
            DoriSheep sheep2 = (DoriSheep) sheep.clone();
            System.out.println(sheep +"  "+sheep.sheep.hashCode());
            System.out.println(sheep1 +"  "+sheep1.sheep.hashCode());
            System.out.println(sheep2 +"  "+sheep2.sheep.hashCode());
            System.out.println("sheep1.sheep==sheep.sheep:"+ (sheep1.sheep==sheep.sheep) );
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

输出:

在这里插入图片描述
结论:浅拷贝后的对象与被拷贝的对象所得到引用变量是同一个实例。

二、深拷贝复制:

目的:使得拷贝后的对象与被拷贝的对象的引用变量不是用一个实例

1、重写克隆方法时指定引用变量类型不同。

class DoriSheep implements Cloneable, Serializable {
    private String name ;
    private  int age ;
    public Sheep sheep;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        DoriSheep newsheep =null;
        try {
            newsheep = (DoriSheep) super.clone();
            newsheep.sheep = (Sheep) sheep.clone();
        }catch (Exception e){
            System.out.println("chucuole ");
        }
        return  newsheep;
    }

    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;
    }



    @Override
    public String toString() {
        return "DoriSheep{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sheep=" + sheep +
                '}';
    }
}

在这里插入图片描述

2、通过输入输出流实现

class DoriSheep implements Cloneable, Serializable {
    private String name ;
    private  int age ;
    public Sheep sheep;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        DoriSheep newsheep =null;
        try {
            newsheep = (DoriSheep) super.clone();
            newsheep.sheep = (Sheep) sheep.clone();
        }catch (Exception e){
            System.out.println("chucuole ");
        }
        return  newsheep;
    }

    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;
    }



    @Override
    public String toString() {
        return "DoriSheep{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sheep=" + sheep +
                '}';
    }
     //深拷贝
    public Object deepClone(){
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        DoriSheep doriSheep = null;

        try{
            //序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this);

            //反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            doriSheep= (DoriSheep) ois.readObject();
            return doriSheep;

        }
        catch (Exception e){
         e.printStackTrace();
        }finally {
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();

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

        }
        return doriSheep;

    }
}

在这里插入图片描述
推荐用第二种,因为第一种每个引用数据类型都要实现对实例的复制,而第二种是写了一个deepclone()方法,利用输入输出流来实现,要在拷贝类中实现Serializable接口。

原型模式缺点:

  • 需要为每个类都配备一个克隆方法,对新类来说也许不难,但对已有的类进行改造时,需要修改其源码,这违反了设计模式中的ocp原则。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值