原型模式

我的未来我决定 提交于 2020-03-17 04:44:32

在有些系统中,存在大量相同或相似对象的创建问题,如果用传统的构造函数来创建对象,会比较复杂且耗时耗资源,用原型模式生成对象就很高效。

1.原型模式的定义和特点

定义:用一个已经创建的实例做为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。
特点:高效

2.原型模式的结构和实现

2.1原型模式的结构

java中提供了对象的clone()方法,所以实现原型模式很简单,原型模式包含以下主要角色:

  • 抽象原型类(Cloneable):规定了具体原型对象必须实现的接口
  • 具体原型类:实现抽象原型类的clone()方法,它是可被复制的对象
  • 访问类:使用具体原型类中的clone()方法来复制对象

结构图
原型模式结构

2.2原型模式的实现

java引用不仅仅有基本数据变量,还有引用变量,所以将原型模式分两种克隆模式:

  1. 浅克隆:仅仅克隆基本数据类型变量,而不克隆引用类型变量
  2. 深克隆:即克隆基本数据类型变量,也克隆引用类型变量

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!