前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式之原型模式【设计模式】

设计模式之原型模式【设计模式】

作者头像
简单的程序员
发布2020-04-20 10:47:17
5040
发布2020-04-20 10:47:17
举报
文章被收录于专栏:奕仁专栏奕仁专栏

最近买了一本设计模式的书籍看了看,发现自己对设计模式没有什么概念,同时,在看某些设计模式的时候发现在项目中应用了不少,但是是哪个设计模式却说不明白!! 不扯皮,今天记录的是原型模式,java中天然支持原型模式,也就是在jdk层面就支持这个了(clone),代理模式也是(Proxy)。

概念

用原型实例制定创建对象的种类,并通过拷贝这些原型并创建新的对象,相当于是拷贝一份副本

看到这个概念的时候我不禁想起了java的Object类的clone方法么? 难怪java天然支持拷贝模型。话说回来,在java中如果实现克隆对象,要有两个标准

  1. 必须要实现人家自带的Cloneable接口
  2. 必须要重写clone方法。
文字太干燥了,直接上栗子:
代码语言:javascript
复制
import lombok.Data;
@Data
public class User implements Cloneable{

    private String name ;

    private int age;

    private int sex;

    @Override
    protected Object clone() {
        try {
         // 这里是重写clone方法的逻辑
            User    user = (User) super.clone();
            return  user;

        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return null;
    }
}

再来上一个测试类:

代码语言:javascript
复制
public class Client {

    public static void main(String[] args) {
        User user = new User();
        user.setAge();
        User cloneUser = (User)user.clone();
        System.out.println(cloneUser);
    }
}
####得到结果 ::User(name=null, age=18, sex=0)

结果: 拷贝成功

原理: 因为需要实现cloneable接口,这个接口它是一个标记接口,没有任何方法(跟Serializable一样),jvm用来对标记的对象执行它的clone方法,然后进行内存二进制流的拷贝,因此性能会比new好很多。

这里问题又来了,如果你克隆的对象里面引用了其他对象呢??试试?

代码语言:javascript
复制
@Data
public class User implements Cloneable{
    //很多根头发
    private ArrayList hairs = new ArrayList();

    private String name ;

    private int age;

    private int sex;

    @Override
    protected Object clone() {
        try {
            User    user = (User) super.clone();
            return  user;

        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return null;
    }
}
public class Client {

    public static void main(String[] args) {
        User user = new User();
        user.setAge();
        user.getHairs().add("aaaa");
        User cloneUser = (User)user.clone();
        cloneUser.getHairs().add("abc");
        System.out.println(cloneUser);
        System.out.println(user);
    }
}
### User(hairs=[aaaa, abc], name=null, age=18, sex=0)
###User(hairs=[aaaa, abc], name=null, age=18, sex=0)

翻车了? 没错,当对象里面引用另外一个对象的时候,它这里其实是引用这个对象的地址,这种拷贝也就是我们常说的浅拷贝,有人说了,String不就是引用的对象么?注意:String它是jdk提供的不可变对象,它内部是通过final类型的char数组实现的,并没有实现clone 方法,因此它是可以直接被克隆的,与此相同的,比如int Integer,long Long …等等都是可以直接被拷贝的。

那诸如上面的情况,应该如何修改呢?也就是如何修改为深拷贝呢? so essy!!!直接对内部的对象引用也执行clone方法

代码语言:javascript
复制
 @Override    protected Object clone() {        try {            User    user = (User) super.clone();            user.hairs = (ArrayList) hairs.clone();            return  user;        }catch (CloneNotSupportedException e){            e.printStackTrace();        }        return null;    } 

对,没错,这里我们在点到ArrayList源码看一下,它是有实现clone方法的

至此,原型模式的栗子就举完毕了 !

原型模式使用场景

  1. 在使用多个对象但又不便于创建多个对象所承担的消耗的时候,可以使用克隆
  2. 通过new一个对象的时候需要很繁琐的进行数据准备,可以使用原型模式对当前对象进行重复修改(一个对象多个修改者的场景)
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-11-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概念
    • 文字太干燥了,直接上栗子:
    • 原型模式使用场景
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档