原型模式是一种创建型的设计模式,主要的特点是通过克隆已有的对象来进行创建,而不需要通过new操作(甚至是一项一项的设置属性)来实现。原型模式特别适合于构造对象成本较大的场景或者对性能要求较高的场景。
主要解决:在运行期建立对象。
使用场景:对象的构造过程比较复杂,成本较高。对性能要求比较高的场景。
关键技术:实现Cloneable
接口,定义clone
方法。
注意事项: 1. 原型模式属于浅拷贝,只能拷贝基础变量;2. clone方法是直接进行内存拷贝,不会调用对象的构造方法。如果对象的构造方法是私有的,也是可以进行clone的。
其实这里的定义clone
方法,相当于是重写父类(Object)的clone
,在下边的代码案例中可以看出。而Object的clone
方法,则是native方法。
// Object.java
protected native Object clone() throws CloneNotSupportedException;
2、实现
2.1、背景
这次用一个动漫的场景来说明原型模式的实现过程,那就是B站动漫的镇站之作品《某科学的超电磁炮》(至于为何是镇站之作,请自行百度)。在动漫中,主角御坂美琴(原始对象),白井黑子和一方通行等人,都具有各自的超能力。在学园都市中想要重新出现一个相同超能力的人毕竟非常困难,但是却可以通过克隆(实现clone方法)的方式来进行制造。而剧情当中就是这样,研究机构获取到了御坂美琴的基因,通过克隆方式制造了非常多的克隆体(克隆对象)来进行使用,而不是把真正的御坂美琴喊过来。
2.2、实现1)定义角色的抽象类
实现Cloneable接口,并且定义clone
方法。
public abstract class RoleInRailGun implements Cloneable
{
private String name;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
abstract String hasSkill();
public Object clone()
{
Object clone = null;
try
{
clone = super.clone();
}
catch (CloneNotSupportedException e)
{
e.printStackTrace();
}
return clone;
}
}
2)定于具体的角色
//白井黑子
public class ShiraiKuroko extends RoleInRailGun
{
public ShiraiKuroko()
{
setName("ShiraiKuroko");
}
@Override
String hasSkill()
{
return "空间转换";
}
}
// 御坂美琴
public class MisakaMikoto extends RoleInRailGun
{
public MisakaMikoto()
{
setName("MisakaMikoto");
}
@Override
String hasSkill()
{
return "炮儿姐无敌,超电磁炮";
}
}
public class Accelerator extends RoleInRailGun
{
public Accelerator()
{
setName("Accelerator");
}
@Override
String hasSkill()
{
return "控制矢量";
}
}
3) 定义克隆工厂
import java.util.HashMap;
public class RoleBuilder
{
private static HashMap<String, RoleInRailGun> roles = new HashMap<String, RoleInRailGun>();
public static void buildRoles()
{
MisakaMikoto misakaMikoto = new MisakaMikoto();
roles.put("MisakaMikoto", misakaMikoto);
ShiraiKuroko shiraiKuroko = new ShiraiKuroko();
roles.put("ShiraiKuroko", shiraiKuroko);
Accelerator accelerator = new Accelerator();
roles.put("Accelerator", accelerator);
}
public static RoleInRailGun getRole(String name)
{
if (!roles.containsKey(name))
{
return null;
}
RoleInRailGun role = roles.get(name);
System.out.println("Role is " + role.getName());
System.out.println("Origin object address is " + role.toString());
RoleInRailGun role_copy = (RoleInRailGun) role.clone();
System.out.println("Origin object address is " + role_copy.toString());
System.out.println("");
return role_copy;
}
}
4) 进行验证
/**
* 验证
*/
public class Demo
{
public static void main(String[] args)
{
RoleBuilder.buildRoles();
RoleInRailGun roleInRailGun1 = RoleBuilder.getRole("MisakaMikoto");
RoleInRailGun roleInRailGun2 = RoleBuilder.getRole("ShiraiKuroko");
}
}
5)运行结果
Role is MisakaMikoto
Origin object address is MisakaMikoto@43a25848
Origin object address is MisakaMikoto@3ac3fd8bRole is ShiraiKuroko
Origin object address is ShiraiKuroko@5594a1b5
Origin object address is ShiraiKuroko@6a5fc7f7Process finished with exit code 0
从运行结果可以看到,原对象和克隆对象是完全的两个对象,两者的内存地址是不同的。
共同学习,写下你的评论
评论加载中...
作者其他优质文章