设计模式01 创建型模式 - 原型模式(Protype Pattern)
参考
3. Cloneable接口和Object的clone()方法 | 博客园
原型模式(Prototype Pattern)
指定创建对象的种类,并且通过拷贝创建新的对象。
原型模式复制的克隆对象≠原对象,内存地址段不同,但是属性状态相同。
角色
| 角色名称 | 中文名称 | 作用描述 |
| Client | 客户类 | 让一个原型克隆自身从而获得新的对象 |
| Prototype | 原型接口 | 声明克隆的接口 |
| ConcretePrototype | 具体原型类 | 实现声明的克隆接口 |
特点
1. 当要克隆的对象比较复杂时,原型模式的克隆方法能简化对象创建过程,提高创建对象效率;
2. 克隆对象保持了原对象的所有属性状态;
3. 原型提供了简化的创建结构;
缺点
1. 深克隆时,要为每一个原型的属性对象都创建克隆方法,可能需要修改原有类实现,不符合对扩展开放、对修改关闭的“开闭”原则;
适用场景
1. 创建对象的过程比较复杂,可以利用已有对象进行复制,如需要深克隆;
2. 需要保持对象状态,或者状态变化较少,可以利用原型克隆对象。
深克隆&浅克隆
克隆:复制一个原有对象,产生一个新对象。[浅克隆,深克隆统称]
浅克隆:会复制所有属性值,如果属性是对象地址/引用,不会复制对象本身,而仅仅是复制对象地址/引用;[仅复制一次对象]
深克隆:不仅会复制所以属性值,而且会复制属性所代表对象本身,如果还包含子对象,也会进行迭代复制;[迭代复制对象]
UML类图

demo
现以一个舰船的小游戏为例。
一般来说,敌舰EnemyShip包含name, damage, size, position 4个共有属性。

代码
1. 创建要克隆的原型EnemyShip接口/抽象类, 以及属性对象Position, Size对应类
EnemyShip抽象类,在clone方法复制position和size对象属性目的是为了进行深克隆。如若是浅克隆可以不用创建新属性对象。
// EnemyShip.java
public abstract class EnemyShip {
protected String name;
protected float damage;
protected Size size;
protected Position position; public abstract EnemyShip clone(); /**
* 打印各属性信息
* 如果具体实现类有新添的属性, 需要重写该方法
*/
public void display() {
System.out.println(this.getClass().toString() + ": [" );
System.out.println("Name: " + getName());
System.out.println("Damage: " + getDamage());
System.out.println("Size: (" + getSize().getWidth() + " , " + getSize().getHeight() + ")");
System.out.println("Position: " + getPosition().getX() + " , " + getPosition().getY() + ")");
System.out.println("]");
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public float getDamage() {
return damage;
} public void setDamage(float damage) {
this.damage = damage;
} public Size getSize() {
return size;
} public void setSize(Size size) {
this.size = size;
} public Position getPosition() {
return position;
} public void setPosition(Position position) {
this.position = position;
} }
Position
// Position.java
public class Position {
private int x;
private int y; public Position(int x, int y) {
this.x = x;
this.y = y;
} public Position(Position p) {
this.x = p.x;
this.y = p.y;
} public int getX() {
return x;
} public void setX(int x) {
this.x = x;
} public int getY() {
return y;
} public void setY(int y) {
this.y = y;
}
}
Size
// Size.java
public class Size {
private int width;
private int height; public Size(int width, int height) {
this.width = width;
this.height = height;
} public Size(Size s) {
this.width = s.width;
this.height = s.height;
} public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
}
2. 创建具体要实现克隆的原型类UFO, Rocket, Ultimate EnemyShip
原型实现类UFOEnemyShip
// UFOEnemyShip
public class UFOEnemyShip extends EnemyShip{ @Override
public EnemyShip clone() {
EnemyShip clone = new UFOEnemyShip(); if(clone != null){ Position p = new Position(this.getPosition());
clone.setPosition(p); Size s = new Size(this.getSize());
clone.setSize(s);
} return clone;
}
/*
public void display() {
System.out.println(this.getClass().toString() + ": [" );
System.out.println("Name: " + getName());
System.out.println("Damage: " + getDamage());
System.out.println("Size: (" + getSize().getWidth() + " , " + getSize().getHeight() + ")");
System.out.println("Position: " + getPosition().getX() + " , " + getPosition().getY() + ")");
}*/
}
原型实现类RocketEnemyShip
// RocketEnemyShip.java
public class RocketEnemyShip extends EnemyShip { @Override
public EnemyShip clone() {
EnemyShip clone = new RocketEnemyShip(); if(clone != null){ Position p = new Position(this.getPosition());
clone.setPosition(p); Size s = new Size(this.getSize());
clone.setSize(s);
} return clone;
} }
原型实现类UltimateEnemyShip
// UltimateEnemyShip.java
public class UltimateEnemyShip extends EnemyShip { @Override
public EnemyShip clone() {
EnemyShip clone = new UltimateEnemyShip(); if(clone != null){ Position p = new Position(this.getPosition());
clone.setPosition(p); Size s = new Size(this.getSize());
clone.setSize(s);
} return clone;
}
}
3. 创建客户类,使用EnemyShip UFO类对象进行克隆Rocket, Ultimiate
客户端类Client
// Client.java
public class Client { public static void main(String[] args) {
// 新建ufo
EnemyShip ufo = new UFOEnemyShip();
ufo.setName("UFO");
ufo.setDamage(15);
ufo.setPosition(new Position(0, 0));
ufo.setSize(new Size(5,5)); // 利用ufo克隆rocket
EnemyShip rocket = ufo.clone();
rocket.setName("Rocket");
rocket.setDamage(20);
rocket.setPosition(new Position(10, 12));
rocket.setSize(new Size(15, 15)); // 利用ufo克隆ultimate
EnemyShip ultimate = ufo.clone();
ultimate.setName("Ultimate");
ultimate.setDamage(100);
ultimate.setPosition(new Position(20, 16));
ultimate.setSize(new Size(30, 30)); // 显示创建对象信息
ufo.display();
rocket.display();
ultimate.display();
}
}
运行结果
Console输出结果
class DesignPattern.UFOEnemyShip: [
Name: UFO
Damage: 15.0
Size: (5 , 5)
Position: 0 , 0)
]
class DesignPattern.UFOEnemyShip: [
Name: Rocket
Damage: 20.0
Size: (15 , 15)
Position: 10 , 12)
]
class DesignPattern.UFOEnemyShip: [
Name: Ultimate
Damage: 100.0
Size: (30 , 30)
Position: 20 , 16)
]
设计模式01 创建型模式 - 原型模式(Protype Pattern)的更多相关文章
- JAVA设计模式 2【创建型】原型模式的理解与使用
在本节中,我们将学习和使用原型模式:这一节学习的原型模式也是创建型 模式的其中之一.再次复习一下:创建型 模式就是描述如何去更好的创建一个对象. 我们都知道,在JAVA 语言中.使用new 关键字创建 ...
- 设计模式01 创建型模式 - 单例模式(Singleton Pattern)
参考 [1] 设计模式之:创建型设计模式(6种) | 博客园 [2] 单例模式的八种写法比较 | 博客园 单例模式(Singleton Pattern) 确保一个类有且仅有一个实例,并且为客户提供一 ...
- 设计模式01 创建型模式 - 建造者模式(Build Pattern)
参考 1. Builder Design Pattern | Youtube 2. 建造者模式(Builder和Director)| 博客园 3. 深入理解Builder模式 | 简书 建造者模式(B ...
- Typescript玩转设计模式 之 创建型模式
作者简介 joey 蚂蚁金服·数据体验技术团队 前言 我们团队的工作是用单页面应用的方式实现web工具.涉及到数万到十数万行的前端代码的管理,而且项目周期长达数年. 怎么样很好地管理好这种量级的前端代 ...
- java设计模式--创建模式--原型模式
原型模式: 原型模式 概述 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 适用性 .当一个系统应该独立于它的产品创建.构成和表示时. .当要实例化的类是在运行时刻指定时,例如,通过 ...
- 设计模式(C#)——04原型模式
推荐阅读: 我的CSDN 我的博客园 QQ群:704621321 在软件开发过程中,我们习惯使用new来创建对象.但是当我们创建一个实例的过程很昂贵或者很复杂,并且需要创建多个这样的 ...
- 设计模式之第9章-原型模式(Java实现)
设计模式之第9章-原型模式(Java实现) “快到春节了,终于快放假了,天天上班好累的说.”“确实啊,最近加班比较严重,项目快到交付了啊.”“话说一到过节,就收到铺天盖地的短信轰炸,你说发短信就发吧, ...
- Java设计模式之创建型模式
创建型模式分为五类:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 一.工厂方法模式:接口-实现类.工厂类
- GoF的23种设计模式之创建型模式的特点和分类
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”.这样可以降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成.就像我们去商场购买商品时, ...
随机推荐
- k8s 部署 custom-metrics-apiserver 时使用 secret 保存 ca 证书遇到的问题
部署 k8s-prometheus-adapter 的 custom-metrics-apiserver 时,pod 总是启动失败,对应的错误日志: unable to install resourc ...
- Git 常用命令总结,掌握这些,轻松驾驭版本管理
原创 最近公司的代码管理工具要从SVN转到Git上,因此虽然之前用过Git,但是都是一些简单的推送提交,因此还是有必要进行一些系统的学习,这里做一下笔记,以备后询,且不定期更新. 关于SVN和Git的 ...
- Jmeter学习之-聚合报告详解
在对接口进行性能测试时,经常用到jmeter的聚合报告来分析数据 首先在待测试的接口或线程组下添加“监听器>聚合报告” 执行请求后,将生成聚合报告,聚合报告包括以下结果参数(中文版+英文版) A ...
- 左偏树(p4431)
难得不是左偏树,而是思维: 这道题在做得时候,有两个性质 1.如果a是一个不下降序列,那么b[i]==a[i]时取得最优解. 2.如果a是一个严格递减序列,则取a序列的中位数x,令b[1]=b[2]= ...
- 解决docker: error pulling image configuration: Get https://registry-1.docker.io/v2/library/mysql/: TLS handshake timeout.
出现这个问题,一般的原因是无法连接到 docker hub,通过: systemctl stop docker echo "DOCKER_OPTS=\"\$DOCKER_OPTS ...
- windows10下VS2013搭建opencv2.4.9吐血之作
1.下载opencv2.4.9.exe文件,然后双击extract文件到指定目录 2.按此链接安装opencv:https://www.cnblogs.com/cuteshongshong/p/405 ...
- [C++_QT] Error: Not a signal or slot declaration
问题: 在Qt工程中添加了一个新的窗口之后 一直报错 如下 单单从错误描述上看 是缺少信号或者槽 但是我确定没有缺少啊 然后第二个错误显示了一个mox_xxxx文件 然后我就去那个目录下去找那个文件 ...
- 重新梳理IT知识之java-05面向对象(一)
一.Java面向对象学习的三条主线: 1.Java类及类的成员:属性.方法.构造器:代码块.内部类 2.面向对象的三大特征:封装性.继承性.多态性.(抽象性) 3.其他关键字:this.super.s ...
- ASP.NET Core搭建多层网站架构【7-使用NLog日志记录器】
2020/01/29, ASP.NET Core 3.1, VS2019, NLog.Web.AspNetCore 4.9.0 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站 ...
- 容器远程访问vnc--CentOS 6.8安装和配置VNC
对于用惯了WIN系统的朋友来说,没有图形化操作界面的Linux用起来实在太难受了.实际上,Linux也是有图形化操作界面的,这就是VNC.接下来本文将告诉大家如何在CentOS 6.8下安装和配置 V ...