一、原型模式介绍

1. 解决的问题

主要解决的问题就是创建重复对象,这部分对象内容本身比较复杂,生成过程可能从库中或者RPC接口中获取数据的耗时较长,因此采用克隆的方式节省时间。

2. 定义

原型模式是一种创建型模式,能够复制已有对象,而又无需使代码依赖它们所属的类。

3.应用场景

  • 对象的初始化需要很多其他对象的数据准备或其他资源的繁琐计算。

  • 需要复制一些对象,同时又希望代码独立于这些对象所属的具体类。

    这种场景通常出现在代码需要处理第三方代码通过接口传递过来的对象时。即使不考虑代码耦合的情况,我们的代码也不能依赖这些对象所属的具体类,因为不知道其具体信息。

    原型模式为我们的代码提供了一个通用接口,我们可以通过这一接口与所有实现了克隆的对象进行交互,使得我们的代码与所克隆的对象具体类独立开。

  • 子类的区别仅在于其对象的初始化方式,可以使用原型模式来减少子类的梳理。

    创建这些子类的目的可能只是为了创建特定类型的对象。

原型模式已与 Java 融为一体,可以随手拿来使用:

  • Objectclone() 方法。
  • Cloneable 接口的实现类,至少可以看到一千多个实现。

4. 浅拷贝与深拷贝

在 Java 中,数据类型分为值类型和引用类型,值类型包括 int、double、byte、boolean、char 等基本数据类型,引用类型包括类、接口、数组等复杂类型。

浅拷贝与深拷贝的主要区别在于是否支持引用类型的成员变量的复制

  1. 浅拷贝

    在浅拷贝中,若原型对象的成员变量是值类型,将复制给克隆对象;若原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,即原型对象和克隆对象的成员变量指向相同的内存地址。

    简单来说,在浅拷贝中,对象被复制时只复制其本身和其包含的值类型的成员变量,而引用类型的成员对象并没有复制

    在 Java 中,通过覆盖 Object 类的 clone() 方法即可实现浅拷贝。

  2. 深拷贝

    在深拷贝中,无论原型变量的成员变量是值类型还是引用类型,都将复制给克隆对象。

    简单来说,在深拷贝中,除了对象本身被复制外,对象所包含的所有成员变量也将复制

    在 Java 中,实现深克隆,可以通过复制引用对象或序列化读取二进制流等方式实现,需要注意的是,能够序列化的对象必须实现 Serializable 接口

    实现 Serializable 读取二进制流示例:

    protected Object deepClone() throws CloneNotSupportedException, IOException, ClassNotFoundException {//将对象写入流中ByteArrayOutputStream bao = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bao);oos.writeObject(this);//将对象从流中取出ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return (ois.readObject());
    }
    

二、原型模式优缺点

1. 优点

  • 可以克隆对象,而无需与其所属的具体类相耦合。
  • 可以克隆生成原型,避免反复运行初始化代码。
  • 可以更方便的生成复杂对象。
  • 可以使用继承以外的方式来处理复杂对象的不同配置。

2. 缺点

  • 克隆包含循环引用的复杂对象可能会非常麻烦。

三、原型模式应用实例:英雄联盟齐天大圣-真假猴王

1. 实例场景

英雄联盟中有一个英雄叫齐天大圣 · 孙悟空,这个名字想必我们都很熟悉,而在英雄联盟中,它的人物背景是这样的:

悟空是一个瓦斯塔亚族的机灵鬼,用自己的力量、灵敏和机智迷惑对手并抢得先机。机缘巧合让他结识了一位剑客并与之成为一生的挚友,这位剑客被人称作易大师。后来,悟空就成为了古老武术门派“无极”的最后一位弟子。如今,附魔长棍傍身的悟空,目标是让艾欧尼亚免遭崩溃的命运。

“我的游记才刚刚开始……”——齐天大圣 · 孙悟空

齐天大圣 · 孙悟空有一个技能叫做真假猴王:

孙悟空进入持续1秒的隐形状态并朝着一个方向突进300距离(不能越过墙体),同时留下一个会攻击附近敌人的分身。

孙悟空的分身会模仿孙悟空的普通攻击和终极技能,但是仅造成35/40/45/50/55%伤害。

今天我们就使用创造孙悟空的分身作为模拟场景。

2. 原型模式实现

2.1 工程结构
builder-pattern
└─ src├─ main│  └─ java│    └─ org.design.pattern.prototype│       ├─ model│          ├─ Hero.java│          └─ WuKong.java└─ test└─ java└─ org.design.pattern.prototype.test└─ WuKongTest.java
2.2 代码实现

英雄基类

/*** 英雄基类*/
@Getter
@Setter
@NoArgsConstructor
public abstract class Hero {/*** 生命值*/protected int healthPoint;/*** 法力值*/protected int magicPoint;/*** 物理伤害*/protected int attackDamage;/*** 法术伤害*/protected int abilityPower;public Hero(Hero hero) {if (hero != null) {this.healthPoint = hero.healthPoint;this.magicPoint = hero.magicPoint;this.attackDamage = hero.attackDamage;this.abilityPower = hero.abilityPower;}}public abstract Hero clone();/*** 攻击*/public void attach() {System.out.printf("This hero’s attack caused %d damage", this.attackDamage);System.out.println();}
}

齐天大圣 · 孙悟空

/*** 齐天大圣孙悟空*/
@Getter
@Setter
@NoArgsConstructor
public class WuKong extends Hero {/*** 物理伤害比例*/protected float attackDamageProportion = 1;public WuKong(WuKong wuKong) {super(wuKong);if (wuKong != null) {this.healthPoint = wuKong.healthPoint;this.magicPoint = wuKong.magicPoint;this.attackDamage =  (int) (wuKong.attackDamage * wuKong.attackDamageProportion);this.abilityPower = wuKong.abilityPower;}}@Overridepublic WuKong clone() {return new WuKong(this);}/*** 攻击*/public void attach() {super.attach();}
}
2.3 测试验证
2.3.1 测试验证类
public class WuKongTest {@Testpublic void testWuKong() {//齐天大圣孙悟空WuKong wuKong = new WuKong();wuKong.setHealthPoint(540);wuKong.setMagicPoint(300);wuKong.setAttackDamage(68);wuKong.setAbilityPower(54);//复制孙悟空分身wuKong.setAttackDamageProportion(0.3f);WuKong fakeKong = wuKong.clone();System.out.println("孙悟空攻击:");wuKong.attach();System.out.println("孙悟空分身攻击:");fakeKong.attach();}
}
2.3.2 测试结果
孙悟空攻击:
This hero’s attack caused 68 damage
孙悟空分身攻击:
This hero’s attack caused 20 damage

四、原型模型结构

  1. 原型 (Prototype) 接口将对克隆方法进行声明。在绝大多数情况下,其中只会有一个名为 clone克隆的方法。
  2. 具体原型 (Concrete Prototype) 类将实现克隆方法。 除了将原始对象的数据复制到克隆体中之外, 该方法有时还需处理克隆过程中的极端情况,例如克隆关联对象和梳理递归依赖等等。
  3. 客户端 (Client) 可以复制实现了原型接口的任何对象。

设计模式并不难学,其本身就是多年经验提炼出的开发指导思想,关键在于多加练习,带着使用设计模式的思想去优化代码,就能构建出更合理的代码。

源码地址:https://github.com/yiyufxst/design-pattern-java

参考资料:
小博哥重学设计模式:https://github.com/fuzhengwei/itstack-demo-design
深入设计模式:https://refactoringguru.cn/design-patterns/catalog

初学 Java 设计模式(五):实战原型模式 「英雄联盟齐天大圣-真假猴王」相关推荐

  1. 重学 Java 设计模式:实战原型模式「上机考试多套试,每人题目和答案乱序排列场景」

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!

  2. 重学 Java 设计模式:实战访问者模式「模拟家长与校长,对学生和老师的不同视角信息的访问场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获!

  3. 重学 Java 设计模式:实战模版模式「模拟爬虫各类电商商品,生成营销推广海报场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获!

  4. 重学 Java 设计模式:实战备忘录模式「模拟互联网系统上线过程中,配置文件回滚场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获!

  5. 重学 Java 设计模式:实战外观模式「基于SpringBoot开发门面模式中间件,统一控制接口白名单场景」

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!

  6. 重学 Java 设计模式:实战组合模式「营销差异化人群发券,决策树引擎搭建场景」

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!

  7. 重学 Java 设计模式:实战策略模式「模拟多种营销类型优惠券,折扣金额计算策略场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获!

  8. 重学 Java 设计模式:实战桥接模式「多支付渠道(微信、支付宝)与多支付模式(刷脸、指纹)场景」

    作者:小傅哥 博客:https://bugstack.cn - 编写系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获!

  9. 重学 Java 设计模式:实战建造者模式「各项装修物料组合套餐选配场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获!

最新文章

  1. php判断一个字符串是否为纯数字,php判断字符串是否为数字
  2. java金钱千分位处理_java对金额的处理,保留两位小数、千分位符
  3. tcp/ip知识点的总结
  4. 函数参数传递、数组指针、二级指针、左值、引用
  5. 项目管理学习总结(5)——产品开发过程中各角色职责说明和技能要求
  6. 别人在抢红包,程序员在研究红包算法
  7. VS C#/C++ 工具箱显示出来 工具箱不见了
  8. 【MATLAB】(三)MATLAB在高等数学中的应用
  9. 64位window 7安装2TB以上大容量硬盘
  10. 微型计算机原理及应用是啥,微型计算机原理及应用(第2版)
  11. 输入一行数字、数字之间用空格隔开python_Python 实现一行输入多个数字(用空格隔开)...
  12. 不花一分钱用自己的live2d出道直播的方法
  13. OkHttp Events事件
  14. 配置OpenWRTnbsp;校园网实现amp;nbsp…
  15. 用AdGuard Home搭建一个内部的DNS服务器,开启局域网内无广告和追踪的浏览体验
  16. 查看linux下tomcat启动日志
  17. python文件处理——pdf解密
  18. python c++情侣网名是什么意思_“果然,他用的是情侣网名!”
  19. Arduino 项目笔记 | 基于 Arduino 单片机的 A4988 和 L298N电机驱动模块实验记录
  20. xp计算机远程桌面连接不了,XP系统如何设置远程桌面连接?XP远程协助连接不上怎么设置?...

热门文章

  1. 超好用的会员VIP邮箱推荐,职场达人都在用的商务邮箱
  2. 享受葡萄酒的极致诱惑
  3. android动态代理机制
  4. 制作一个简单的ALU(支持加减乘除功能)
  5. 白天看投影仪什么牌子效果好?卧室投影仪什么牌子好
  6. Qt中如何使窗口隐藏/最小化到托盘
  7. 使用Android开发打电话程序详细
  8. VMware虚拟机设置统一网段
  9. 精通魔鬼班C语言专业课,专接本 选择精通 精通教育集团.doc
  10. 乐视云计算被列入失信名单:需承担执行费共逾300万