Skip to main content
 首页 » 编程设计

Java 原型模式

2022年07月19日151qlqwjy

1.原型模式简介

说白了原型模式(Prototype Pattern)就是使用一个存在的对象高效地创建多个重复的对象。属于创建型模式。做法是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。

关键代码:实现克隆操作,继承 Cloneable接口,重写clone()方法。
应用实例:细胞分裂、java中的Object clone()方法。
优点:性能提高、逃避构造函数的约束(注意使用clone()方法创建的对象不会调用构造方法)
使用场景:
a.资源优化场景。
b.类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
c.性能和安全要求的场景。
d.通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
e.一个对象多个修改者又不想互相产生影响的场景。
f.一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
g.在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与 Java 融为浑然一体,大家可以随手拿来使用。

注意事项:与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现 Cloneable,重写,深拷贝是通过实现 Serializable 读取二进制流。

2.Demo

import java.util.Hashtable; //注意table的t是小写的! 
 
abstract class Shape implements Cloneable { //使用clone第一步:实现Cloneable接口 
    private String id; 
    protected String type; 
 
    public Shape() { 
        System.out.println("Shape()"); 
    } 
 
    public String getType() { 
        return this.type; 
    } 
 
    public String getId() { 
        return this.id; 
    } 
 
    public void setId(String id) { 
        this.id = id; 
    } 
 
    /*public也是可以的,扩大权限可以,缩小权限不行*/ 
    protected Object clone() throws CloneNotSupportedException { //使用clone第二步:复写clone()方法 
        return super.clone(); 
    } 
} 
 
class Rectangle extends Shape { 
    public Rectangle() { 
        this.type = "Rectangle"; 
        System.out.println("Rectangle"); 
    } 
 
    public void printInfo() { 
        System.out.println("Rectangle: printInfo()"); 
    } 
} 
 
class Square extends Shape { 
    public Square() { 
        this.type = "Square"; 
        System.out.println("Square"); 
    } 
 
    public void printInfo() { 
        System.out.println("Square: printInfo()"); 
    } 
} 
 
class ShapeCache { 
    private static Hashtable<String, Shape> table = new Hashtable<String, Shape>(); 
     
    public static void shapeCache() { 
        Rectangle rect = new Rectangle(); 
        rect.setId("Rectangle"); 
        table.put(rect.getId(), rect); 
 
        Square squ = new Square(); 
        squ.setId("Square"); 
        table.put(squ.getId(), squ); 
    } 
 
    public static Shape getShape(String id) { //提供一个获取新实例的方法 
        Shape shape = table.get(id); //提供一个找出正确实例原型的方法 
        try { 
            return (Shape)shape.clone(); //委托复制实例的方法生成新实例 
        } catch (Exception e) { //CloneNotSupportedException e 和 Exception e 都是可以的,后者应该是前者的父类 
            return null; 
        } 
    } 
} 
 
 
public class PrototypePatternDemo { 
    public static void main(String args[]) { 
        ShapeCache.shapeCache(); 
 
        /*可以使用那一个原型克隆出一组对象*/ 
        Shape rect1 = ShapeCache.getShape("Rectangle");  
        Shape rect2 = ShapeCache.getShape("Rectangle"); 
        Shape rect3 = ShapeCache.getShape("Rectangle"); 
        System.out.println(rect1); 
        System.out.println(rect2); 
        System.out.println(rect3); 
 
        Shape squ1 = ShapeCache.getShape("Square"); 
        Shape squ2 = ShapeCache.getShape("Square"); 
        Shape squ3 = ShapeCache.getShape("Square"); 
        System.out.println(squ1); 
        System.out.println(squ2); 
        System.out.println(squ3); 
    } 
} 
 
 
/* 
$ java PrototypePatternDemo  
Shape()            //注意构造方法只调用了2次! 
Rectangle 
Shape() 
Square 
Rectangle@40c84051 
Rectangle@1af6a711 
Rectangle@37525aeb 
Square@7fcf16ac 
Square@74d9b7c1 
Square@1af1bd6 
*/

参考:http://www.runoob.com/design-pattern/prototype-pattern.html


本文参考链接:https://www.cnblogs.com/hellokitty2/p/10704637.html
阅读延展