• 【设计模式


    1、模式简介

    原型模式的定义:

      通过复制一个现有的对象(原型)来得到一个相似的对象。

    原型模式的UML图如下图所示:

     

      从上图中可以看到,所有的对象实体类都是继承自一个Prototype的父类,而prototype类有一个可以复制对象的方法clone(),可以复制其任意子类。这样,所有Prototype类的子类在整个程序中只需要new一次,其他情况下只需要从这几个类中clone即可。

    原型模式的适用场景:

    • 当系统中需要重复的使用某一些类的对象时;
    • 当这些对象的差别不是很大或完全相同时;
    • 当一个类的对象必须在某几种状态之中时;
    • 当系统需要对对象进行缓存时。

    原型模式的优点:

    • 克隆一般是在内存中以流的形式进行的,比创建一个对象速度快,因此原型模式可以提高系统的性能;
    • 克隆对象的时候可以完全忽略类中的构造方法的访问权限,因此逃避构造函数的约束。

    原型模式的缺点:

    • 克隆并不是对所有的数据类型都适用,有些内部类(如ArrayList)是不支持克隆的;
    • 克隆会忽略构造函数的约束,因此对于一些单例的类也会生成克隆对象,容易导致系统错误。

    2、案例代码

    需求:

      有三种形状圆形(Circle)、矩形(Rectangle)和三角形(Triangle)。多次调用这些形状排成一个队列集合。

    分析:

      我们可以把这个题目中的几个逻辑想象成如下图所示的关系:

     

      我们让圆形(Circle)、矩形(Rectangle)和三角形(Triangle)三种图形继承Shape父类,然后在缓存ShapeCache类中的HashMap中分别缓存三种形状,当主函数中需要某种形状的时候,我们就从缓存中克隆一个使用。

    说明:

      在JAVA中有一个Cloneable接口,是专门用来实现原型模式的。只需要让一个类实现这个接口,重写Object类的clone()方法,就可以方便的实现原型模式了。

    代码:

    1)  原型父类Shape:

    public class Shape implements Cloneable {
                protected String type;
     
                @Override
                protected Object clone() {
                     Shape shape = null;
                     try {
                           shape = (Shape) super.clone();
                      }catch (CloneNotSupportedException e) {
                           e.printStackTrace();
                     }
                     return shape;
                }
     
                public void introduce() {
                     System.out.println("This is a " + type);
                }
    }

    2)  Shape的子类(以Circle类为例):

    public class Circle extends Shape {
     
                public Circle() {
                     super.type = "Circle";
                }
    }

    3)  缓存类ShapeCache:

    public class ShapeCache {
                private Map<String, Shape> shapes;
     
                public ShapeCache() {
                     loadCache();
                }
     
                private void loadCache() {
                      shapes = new HashMap<>();
                     shapes.put("circle", new Circle());
                     shapes.put("rectangle", new Rectangle());
                     shapes.put("triangle", new Triangle());
                }
     
                public Shape getShape(String id) {
                     Shape shape = shapes.get(id);
                     return (Shape) shape.clone();
                }
    }

    4)  测试类Test:

    public class Test {
                public static void main(String[] args) {
                     List<Shape> shapeList = new ArrayList<>();
     
                      ShapeCachecache = new ShapeCache();
                     shapeList.add(cache.getShape("triangle"));
                     shapeList.add(cache.getShape("circle"));
                     shapeList.add(cache.getShape("rectangle"));
                     shapeList.add(cache.getShape("circle"));
                     shapeList.add(cache.getShape("rectangle"));
                     shapeList.add(cache.getShape("triangle"));
                     shapeList.add(cache.getShape("rectangle"));
                     shapeList.add(cache.getShape("circle"));
     
                     for (Shape shape : shapeList) {
                           shape.introduce();
                     }
                }
    }

    5)  运行结果如下图所示:

    3、扩展

      上面说过,JAVA中为我们提供了一个Cloneable接口,只有实现了这个接口之后,重写Object类中的clone()方法才有效,否则会报CloneNotSupportedException异常。

      使用原型模式复制对象时不会调用类的构造方法,因为复制出来的对象是原型对象复制粘贴出来的,是直接在内存中复制数据,因此不会调用到类的构造方法,甚至连访问权限都对原型模式无效,这一点在编程时需要特别注意。

      Object类的clone()方法只能拷贝对象中的8种基本数据类型,对于数组、容器、引用对象等都不会拷贝,这种现象被成为浅拷贝。与浅拷贝对应的是深拷贝,即在对对象进行浅拷贝之后,将对象中的数组、容器、引用对象单独进行拷贝。

      最后贴出原型模式的GitHub地址:【GitHub - Prototype】

  • 相关阅读:
    这是一棵树吗
    感染者
    es6 语法
    css3 flex 详解,可以实现div内容水平垂直居中
    移动端实现复制内容至剪贴板小例子
    jq+mui 阻止事件冒泡
    移动端H5 判断IOS还是Android 平台
    移动端布局 rem,和px
    关于H5移动端开发 iPhone X适配
    H5 微信公众号 监听返回事件
  • 原文地址:https://www.cnblogs.com/itgungnir/p/6211092.html
Copyright © 2020-2023  润新知