Java 23种设计模式 之 原型模式

原型模式,以一个对象为原型进行复制(克隆)的设计模式,故引申出来深克隆与浅克隆知识。

原型模式解决的问题

举个例子:比如我们要抄袭某位博主的博客,博客包括 标题,正文,文末的引流链接
我们有两个类

原型 - Blog类

public class Blog {

    String title = "被抄袭的博客标题";
    String text = "被抄袭的博客正文";
    ReferenceLink referenceLink = new ReferenceLink();//文末的引流链接

    public Blog() {
    }

    public Blog(String title, String text, ReferenceLink referenceLink) {
        this.title = title;
        this.text = text;
        this.referenceLink = referenceLink;
    }

    public String getTitle() {
        return title;
    }

    public String getText() {
        return text;
    }

    public ReferenceLink getReferenceLink() {
        return referenceLink;
    }
}
@Override
    public String toString() {
        return "Blog{" +
                "title='" + title + '\'' +
                ", text='" + text + '\'' +
                ", referenceLink=" + referenceLink.QQ + referenceLink.str +
                '}';
    }

引流链接类

public class ReferenceLink {

   String QQ = "qq466009264";
    String str = "来骚扰我呀";

    public String getQQ() {
        return QQ;
    }

    public String getStr() {
        return str;
    }

    public void setQQ(String QQ) {
        this.QQ = QQ;
    }

    public void setStr(String str) {
        this.str = str;
    }
}

现在开始抄袭了

		Blog yblog = new Blog();//原博客
        Blog cblog = new Blog(yblog.title,yblog.text,yblog.referenceLink);//将原博客抄袭
        System.out.println("原博客"+yblog);
        System.out.println("抄袭博客"+cblog);
        System.out.println(yblog.hashCode() == cblog.hashCode());

在这里插入图片描述
false表示不相等,抄袭成功
思考,这种方式的弊端。

  1. 太累了,不能一次性全部抄袭,要一步一步来,先标题,后正文等等。
  2. 硬编码,博客可能没有正文,只有引流链接,代码就要修改。

那么怎么解决这个问题呢?

利用object的方法,即object.clone。

  • 实现Cloneable
  • 调用clone方法
public class Blog implements Cloneable{

    String title = "被抄袭的博客标题";
    String text = "被抄袭的博客正文";
    ReferenceLink referenceLink = new ReferenceLink();

    public Blog() {
    }

    public Blog(String title, String text, ReferenceLink referenceLink) {
        this.title = title;
        this.text = text;
        this.referenceLink = referenceLink;
    }

    public String getTitle() {
        return title;
    }

    public String getText() {
        return text;
    }

    public ReferenceLink getReferenceLink() {
        return referenceLink;
    }

    @Override
    public String toString() {
        return "Blog{" +
                "title='" + title + '\'' +
                ", text='" + text + '\'' +
                ", referenceLink=" + referenceLink.QQ + referenceLink.str +
                '}';
    }

    public static void main(String[] args) throws CloneNotSupportedException {

        Blog yblog = new Blog();//原博客
        Blog cblog = (Blog)yblog.clone();//将原博客抄袭
        System.out.println("原博客"+yblog);
        System.out.println("抄袭博客"+cblog);
        System.out.println(yblog.hashCode() == cblog.hashCode());
    }
}

在这里插入图片描述
结果似乎表明也抄袭成功了。

当抄袭者怕被发现将原博客升级

在这里插入图片描述

我们再次运行输出结果
在这里插入图片描述
观察可知,其实只是克隆了其基本数据类型,引用数据类型并没有完全克隆,引用数据类型克隆的是引用地址,也就是说当副本改变引用数据类型时,原型也同步改变。

数据类型
在这里插入图片描述

深克隆与浅克隆

深克隆: 克隆包括引用类型,开辟新空间,将值填进去
浅克隆: 克隆不包括引用类型,复制的是引用类型的地址

深克隆

ReferenceLink 类

import java.io.Serializable;

public class ReferenceLink implements Cloneable, Serializable {

    String QQ = "qq466009264";
    String str = "来骚扰我呀";

    public String getQQ() {
        return QQ;
    }

    public String getStr() {
        return str;
    }

    public void setQQ(String QQ) {
        this.QQ = QQ;
    }

    public void setStr(String str) {
        this.str = str;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

Blog 类

ublic class Blog implements Cloneable{

    String title = "被抄袭的博客标题";
    String text = "被抄袭的博客正文";
    ReferenceLink referenceLink = new ReferenceLink();



    public Blog() {
    }

    public Blog(String title, String text, ReferenceLink referenceLink) {
        this.title = title;
        this.text = text;
        this.referenceLink = referenceLink;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setText(String text) {
        this.text = text;
    }

    public void setReferenceLink(ReferenceLink referenceLink) {
        this.referenceLink = referenceLink;
    }

    public String getTitle() {
        return title;
    }

    public String getText() {
        return text;
    }

    public ReferenceLink getReferenceLink() {
        return referenceLink;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Blog blog ;
        blog = (Blog) super.clone();

        blog.referenceLink = (ReferenceLink) referenceLink.clone();
        return blog;
    }

    @Override
    public String toString() {
        return "Blog{" +
                "title='" + title + '\'' +
                ", text='" + text + '\'' +
                ", referenceLink=" + referenceLink.QQ + referenceLink.str +
                '}';
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        Blog yblog = new Blog();//原博客
        Blog cblog = (Blog)yblog.clone();//将原博客抄袭
        cblog.setTitle("升级版被抄袭的博客标题");
        cblog.setText("升级版被抄袭的博客正文");
        cblog.referenceLink.setQQ("抄袭者的qq");
        cblog.referenceLink.setStr("别来烦我哦");
        System.out.println("原博客"+yblog);
        System.out.println("抄袭博客"+cblog);
        System.out.println(yblog.hashCode() == cblog.hashCode());

    }
}

看结果抄袭完全成功
在这里插入图片描述
方式一:分别对引用类型赋值克隆
方式二:序列化和反序列化

posted @   长勺  阅读(26)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示