参考
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) ]