在有些系统中,存在大量相同或相似对象的创建问题,如果用传统的构造函数来创建对象,会比较复杂且耗时耗资源,用原型模式生成对象就很高效。
1.原型模式的定义和特点
定义:用一个已经创建的实例做为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。
特点:高效
2.原型模式的结构和实现
2.1原型模式的结构
java中提供了对象的clone()方法,所以实现原型模式很简单,原型模式包含以下主要角色:
- 抽象原型类(Cloneable):规定了具体原型对象必须实现的接口
- 具体原型类:实现抽象原型类的clone()方法,它是可被复制的对象
- 访问类:使用具体原型类中的clone()方法来复制对象
结构图:
2.2原型模式的实现
java引用不仅仅有基本数据变量,还有引用变量,所以将原型模式分两种克隆模式:
- 浅克隆:仅仅克隆基本数据类型变量,而不克隆引用类型变量
- 深克隆:即克隆基本数据类型变量,也克隆引用类型变量
2.2.1 浅克隆
Java中的Object类提供了浅克隆的clone()方法,具体原型类只要实现Cloneable接口就可实现对象的浅克隆,cloneable类就是抽象原型类。
1.具体抽象类
public class RealizeType implements Cloneable{
private String name;
private Student student;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public RealizeType() {
System.out.println("具体原型类创建成功");
}
@Override
public String toString() {
return "RealizeType{" +
"name='" + name + '\'' +
", student=" + student +
'}';
}
@Override
public Object clone() throws CloneNotSupportedException {
System.out.println("具体原型类复制成功");
return (RealizeType)super.clone();
}
}
public class Student implements Cloneable{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(){
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return (Student)super.clone();
}
}
2.访问类
public class TestMain {
public static void main(String[] args) throws CloneNotSupportedException {
RealizeType realizeType1 = new RealizeType();
realizeType1.setName("张三");
Student student1 = new Student();
student1.setName("s1");
realizeType1.setStudent(student1);
RealizeType realizeType2 = (RealizeType) realizeType1.clone();
realizeType2.setName("李四");
System.out.println(realizeType1);
System.out.println(realizeType2);
System.out.println("realizeType1 == realizeType2 ?" + (realizeType1 == realizeType2));
System.out.println("realizeType1.student == realizeType2.student?"+(realizeType1.getStudent()==realizeType2.getStudent()));
}
}
3.运行结果
具体原型类创建成功
具体原型类复制成功
RealizeType{name='张三', student=Student{name='s1'}}
RealizeType{name='李四', student=Student{name='s1'}}
realizeType1 == realizeType2 ?false
realizeType1.student == realizeType2.student?true
2.2.2深克隆
1.具体抽象类
public class RealizeType implements Cloneable {
private String name;
private Student student;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public RealizeType() {
System.out.println("具体原型类创建成功");
}
@Override
public String toString() {
return "RealizeType{" +
"name='" + name + '\'' +
", student=" + student +
'}';
}
@Override
public Object clone() throws CloneNotSupportedException {
System.out.println("具体原型类复制成功");
RealizeType realizeType = (RealizeType)super.clone();
realizeType.setStudent((Student)realizeType.getStudent().clone());
return realizeType;
}
}
public class Student implements Cloneable{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(){
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return (Student)super.clone();
}
}
2.访问类
public class TestMain {
public static void main(String[] args) throws CloneNotSupportedException {
RealizeType realizeType1 = new RealizeType();
realizeType1.setName("张三");
Student student1 = new Student();
student1.setName("s1");
realizeType1.setStudent(student1);
RealizeType realizeType2 = (RealizeType) realizeType1.clone();
realizeType2.setName("李四");
System.out.println(realizeType1);
System.out.println(realizeType2);
System.out.println("realizeType1 == realizeType2 ?" + (realizeType1 == realizeType2));
System.out.println("realizeType1.student == realizeType2.student?"+(realizeType1.getStudent()==realizeType2.getStudent()));
}
}
3.运行结果
RealizeType{name='张三', student=Student{name='s1'}}
RealizeType{name='李四', student=Student{name='s1'}}
realizeType1 == realizeType2 ?false
realizeType1.student == realizeType2.student?false
3.原型模式的应用场景
- 对象之间相同或相似,即只有个别几个属性不同时
- 对象创建过程比较麻烦,但是复制比较简单
4.原型模式的扩展
原型模式可扩展为带原型管理器的原型模式,在原有模型的基础上增加一个原型管理器,该类用hashMap保存多个复制的原型,client类可以通过管理器get id(String id) 方法获取复制的原型。
结构图:
例子:通过原型管理器计算圆和正方形面积
package realizetype;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
interface Shape extends Cloneable {
/**
* 计算面积
*/
void area();
}
class Circular implements Shape {
@Override
public Object clone() {
Cloneable c = null;
try {
c = (Circular) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
System.out.println("圆形克隆失败");
}
return c;
}
/**
* 计算面积
*/
@Override
public void area() {
System.out.print("这是一个圆,请输入圆的半径:");
Scanner input = new Scanner(System.in);
int r = input.nextInt();
System.out.println("圆的面积:" + 3.1415926 * r * r);
}
}
class Square implements Shape {
@Override
public Object clone() {
Square s = null;
try {
s = (Square) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
System.out.println("正方形克隆失败");
}
return s;
}
/**
* 计算面积
*/
@Override
public void area() {
System.out.print("这是一个正方形,请输入正方形边长:");
Scanner input = new Scanner(System.in);
int a = input.nextInt();
System.out.println("正方形的面积:" + a * a);
}
}
class ProtoTypeManager {
private Map<String, Shape> hashMap = new HashMap<>();
public ProtoTypeManager() {
hashMap.put("circular", new Circular());
hashMap.put("square", new Square());
}
public void addShape(String s, Shape shape) {
hashMap.put(s, shape);
}
public Shape getShape(String s) {
return hashMap.get(s);
}
}
class TestMain {
public static void main(String[] args) {
ProtoTypeManager protoTypeManager = new ProtoTypeManager();
Shape shape1 = protoTypeManager.getShape("circular");
shape1.area();
Shape shape2 = protoTypeManager.getShape("square");
shape2.area();
}
}
运行结果:
这是一个圆,请输入圆的半径:1
圆的面积:3.1415926
这是一个正方形,请输入正方形边长:1
正方形的面积:1
来源:CSDN
作者:EmptyBamboo
链接:https://blog.csdn.net/weixin_41439556/article/details/104900033