设计模式01 创建型模式

参考

1. 设计模式:原型模式 | 博客园

2. Java clone深拷贝、浅拷贝 | CSDN

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

  

原文地址:https://www.cnblogs.com/fortunely/p/9800807.html