对原型模式的理解

目录

  • [一、原型模式 vs. 传统的复制对象](#一、原型模式 vs. 传统的复制对象)
    • 1、传统的复制对象
    • 2、原型模式
      • [2.1 原型模式是什么?](#2.1 原型模式是什么?)
      • [2.2 如何实现呢?(原型模式的思想)](#2.2 如何实现呢?(原型模式的思想))
      • [2.3 对原型的理解](#2.3 对原型的理解)
      • [2.4 示例](#2.4 示例)
        • [2.4.1 示例1:Java 的 Cloneable (可克隆) 接口就是立即可用的原型模式](#2.4.1 示例1:Java 的 Cloneable (可克隆) 接口就是立即可用的原型模式)
        • [2.4.2 示例2:克隆时,用户没传入具体的类](#2.4.2 示例2:克隆时,用户没传入具体的类)

一、原型模式 vs. 传统的复制对象

  • 第一次看到原型模式这个名字时,我是懵逼的。这是啥意思啊?
  • 看了相关介绍后,我更懵逼了,这原型模式不就是复制对象吗?这也能算一种设计模式?

1、传统的复制对象

  • 传统的复制对象:必须new一个属于相同类的对象。 然后,必须遍历原始对象的所有成员变量, 并将成员变量值复制到新对象中。
java 复制代码
// 示例
public class User {
    @Getter
    @Setter
    private String name;

    @Setter
    private String ak;

    @Setter
    @Getter
    private String sk;
}

public class UserService {
    public void doProcess(User user) {
        // 要求拷贝user
        User copyedUser = new User();

        copyedUser.setName(user.getName());
        copyedUser.setSk(user.getSk());
//        copyedUser.setAk(user.getAk()); // 错误
    }
}
  • 这里有个小问题: 有些对象可能拥有私有成员变量, 它们在对象本身以外是不可见的(如User的ak字段)。
  • 传统的复制还有另外一个问题必须知道对象所属的类才能创建复制品, 所以代码必须依赖该类
  • 还可能有另外一个问题: 有时只知道对象所实现的接口, 而不知道其所属的具体类, 比如向方法的某个参数传入实现了某个接口的任何对象。
java 复制代码
public void execute(IBuy user) {
        
}

2、原型模式

2.1 原型模式是什么?

  • 原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。(低耦合)

2.2 如何实现呢?(原型模式的思想)

  • 原型模式将克隆过程委派给被克隆的实际对象(让传入的对象自身具有克隆能力,调用该对象的克隆(clone)方法,即可完成克隆)。
    • 在clone方法中,(1)由于知道自己所属的类,自然可以轻轻松松new一个当前类的对象。(2)由于类中的方法也能访问自己的私有成员变量,因此,可以毫无阻力的将原始对象所有的成员变量值复制到新建对象中。【原型模式解决了传统复制对象的3个问题

2.3 对原型的理解

  • 原型 并不是计算机的独有概念,而是生活中的常见概念。当一个产品原型被验证是成功的,后续会被大量复制,并被销售到全国。因此,原型的本质就是被复制。
    • 支持克隆(被复制)的对象即为原型。

2.4 示例

2.4.1 示例1:Java 的 Cloneable (可克隆) 接口就是立即可用的原型模式
java 复制代码
@ToString
public class User implements Cloneable {
    @Getter
    @Setter
    private String name;

    @Setter
    private String ak;

    @Setter
    @Getter
    private String sk;

    @Override
    public User clone() {
        try {
            return (User) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}

public class Application {
    public static void main(String[] args) {
        User user = new User();
        user.setName("张三");
        user.setAk("123456");
        user.setSk("654321");

        User clonedUser = user.clone();
        System.out.println(clonedUser);
    }
}

/**
User(name=张三, ak=123456, sk=654321)
*/
  • Cloneable仅仅是一个用于标识的接口,里面啥都没有。
java 复制代码
public interface Cloneable {
}
  • Object提供了clone方法
java 复制代码
protected native Object clone() throws CloneNotSupportedException;
  • 一个类想用Object的clone()方法,那么就必须实现Cloneable接口,否则会抛异常:CloneNotSupportedException。
2.4.2 示例2:克隆时,用户没传入具体的类
java 复制代码
public abstract class Shape implements Cloneable {
    @Override
    public Shape clone() throws CloneNotSupportedException {
        return (Shape) super.clone();
    }
}

@Data
public class Circle extends Shape {
    /**
     * 半径
     */
    private int radius;
}

@Data
public class Rectangle extends Shape {
    private int width;
    private int height;
}

public class Application {
    public static void main(String[] args) {
        Circle circle = new Circle();
        circle.setRadius(10);

        Rectangle rectangle = new Rectangle();
        rectangle.setHeight(15);
        rectangle.setWidth(5);

        List<Shape> shapes = new ArrayList<>();
        shapes.add(circle);
        shapes.add(rectangle);

        shapes.stream().forEach(shape -> {
            try {
                Shape clonedShape = shape.clone();
                System.out.println(clonedShape);
            } catch (CloneNotSupportedException e) {
                throw new RuntimeException(e);
            }
        });
    }
}
  • 即使没传入具体的类(Shape是抽象类),也能完成克隆。
相关推荐
老菜鸟的每一天4 小时前
创建型模式-Prototype 模式(原型模式)
设计模式·原型模式
道友老李3 天前
【设计模式精讲】创建型模式之原型模式(深克隆、浅克隆)
设计模式·原型模式
Samson Bruce4 天前
【创建模式-原型模式(Prototype Pattern)】
原型模式
強云5 天前
23种设计模式 - 原型模式
设计模式·原型模式
le_duoduo6 天前
原型模式详解(Java)
java·原型模式
lonelyhiker6 天前
javascript的原型链
开发语言·javascript·原型模式
新时代的弩力7 天前
Function.prototype.__proto__==Object.prototype
开发语言·javascript·原型模式
无限大.9 天前
前端知识速记—JS篇:原型与原型链
前端·javascript·原型模式
wy02_9 天前
【设计模式】 建造者模式和原型模式
设计模式·建造者模式·原型模式
ox008011 天前
C++ 设计模式-原型模式
c++·设计模式·原型模式