【设计模式】【5】原型设计模式

原型设计模式(Clone)

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

案例说明

复制图形

UML图

在这里插入图片描述

  1. 原型(Prototype)接口将对克隆方法进行声明。在绝大多数 情况下,其中只会有一个名为 clone 克隆 的方法。
  2. 具体原型(Concrete Prototype)类将实现克隆方法。除了将 原始对象的数据复制到克隆体中之外,该方法有时还需处理 克隆过程中的极端情况,例如克隆关联对象和梳理递归依赖 等等。
  3. 客户端(Client)可以复制实现了原型接口的任何对象。

原型注册表
在这里插入图片描述

  1. 原型注册表(Prototype Registry)提供了一种访问常用原型 的简单方法,其中存储了一系列可供随时复制的预生成对象。 最简单的注册表原型是一个 名称 → 原型 的哈希表。 但如 果需要使用名称以外的条件进行搜索,你可以创建更加完善 的注册表版本。

核心代码

shapes/Shape

import java.util.Objects;

/**
 * @author: ccyy
 * @create: 2021-11-05
 * @description: 通用形状接口
 **/
public abstract class Shape{
    public int x;
    public int y;
    public String color;

    public Shape() {
    }

    public Shape(Shape target){
        if (target!=null) {
            this.x = target.x;
            this.y = target.y;
            this.color = target.color;
        }
    }

    public abstract Shape clone();

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Shape))
            return false;
        Shape shape2 = (Shape) obj;
        return shape2.x == x && shape2.y == y && Objects.equals(shape2.color,color);
    }
}

shapes/Circle

/**
 * @author: ccyy
 * @create: 2021-11-05
 * @description: 圆形
 **/
public class Circle extends Shape{
    public int radius;
    public Circle(){

    }
    public Circle(Circle target){
        super(target);
        if (target!=null) {
            this.radius = target.radius;
        }
    }
    @Override
    public Shape clone() {
        return new Circle(this);
    }

    @Override
    public boolean equals(Object object2) {
        if (!(object2 instanceof Circle) || !super.equals(object2)) return false;
        Circle shape2 = (Circle) object2;
        return shape2.radius == radius;
    }
}

shapes/Circle
/**
 * @author: ccyy
 * @create: 2021-11-05
 * @description: 长方形
 **/
public class Rectangle extends Shape{
    public int width;
    public int height;
    public Rectangle(){}
    public Rectangle(Rectangle target){
        super(target);
        if (target != null) {
            this.width = target.width;
            this.height = target.height;
        }
    }
    @Override
    public Shape clone() {
        return new Rectangle(this);
    }

    @Override
    public boolean equals(Object object2) {
        if (!(object2 instanceof Rectangle) || !super.equals(object2)) return false;
        Rectangle shape2 = (Rectangle) object2;
        return shape2.width == width && shape2.height == height;
    }
}
Main
import com.ccyy.designPattern.creational.clone.shapes.Circle;
import com.ccyy.designPattern.creational.clone.shapes.Rectangle;
import com.ccyy.designPattern.creational.clone.shapes.Shape;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: ccyy
 * @create: 2021-11-05
 * @description: 演示
 **/
public class Main {
    public static void main(String[] args) {
        List<Shape> shapes = new ArrayList<>();
        List<Shape> shapesCopy = new ArrayList<>();

        Circle circle = new Circle();
        circle.x = 10;
        circle.y = 20;
        circle.radius = 15;
        circle.color = "red";
        shapes.add(circle);

        Circle anotherCircle = (Circle) circle.clone();
        shapes.add(anotherCircle);

        Rectangle rectangle = new Rectangle();
        rectangle.width = 10;
        rectangle.height = 20;
        rectangle.color = "blue";
        shapes.add(rectangle);

        cloneAndCompare(shapes, shapesCopy);
    }
    private static void cloneAndCompare(List<Shape> shapes, List<Shape> shapesCopy) {
        for (Shape shape : shapes) {
            shapesCopy.add(shape.clone());
        }

        for (int i = 0; i < shapes.size(); i++) {
//            shapes.get(i) != shapesCopy.get(i) 比较的是内存地址,内存地址不一样,不是同一个对象
            if (shapes.get(i) != shapesCopy.get(i)) {
                System.out.println(i + ": 不是同一个对象");
                if (shapes.get(i).equals(shapesCopy.get(i))) {
                    System.out.println(i + ": 它们是一样的");
                } else {
                    System.out.println(i + ": 但它们并不完全相同");
                }
            } else {
                System.out.println(i + ": 属于同一个对象");
            }
        }
    }
}

适用场景

  • 如果你需要复制一些对象,同时又希望代码独立于这些对象 所属的具体类,可以使用原型模式。
  • 这一点考量通常出现在代码需要处理第三方代码通过接口传 递过来的对象时。即使不考虑代码耦合的情况,你的代码也 不能依赖这些对象所属的具体类,因为你不知道它们的具体 信息。
  • 如果子类的区别仅在于其对象的初始化方式,那么你可以使 用该模式来减少子类的数量。别人创建这些子类的目的可能 是为了创建特定类型的对象。
  • 在原型模式中,你可以使用一系列预生成的、各种类型的对 象作为原型。

优缺点

优点

  • 你可以克隆对象,而无需与它们所属的具体类相耦合。
  • 你可以克隆预生成原型,避免反复运行初始化代码。
  • 你可以更方便地生成复杂对象。
  • 你可以用继承以外的方式来处理复杂对象的不同配置。

缺点

  • 克隆包含循环引用的复杂对象可能会非常麻烦。

与其他模式的关系

  • 在许多设计工作的初期都会使用工厂方法(较为简单,而且 可以更方便地通过子类进行定制),随后演化为使用抽象工 厂、原型或生成器(更灵活但更加复杂)。
  • 抽象工厂模式通常基于一组工厂方法,但你也可以使用原型 模式来生成这些类的方法。
  • 原型可用于保存命令的历史记录。 • 大量使用组合和装饰的设计通常可从对于原型的使用中获益。 你可以通过该模式来复制复杂结构,而非从零开始重新构造。
  • 原型并不基于继承,因此没有继承的缺点。另一方面,原型 需要对被复制对象进行复杂的初始化。 工厂方法基于继承, 但是它不需要初始化步骤。
  • 有时候原型可以作为备忘录的一个简化版本,其条件是你需 要在历史记录中存储的对象的状态比较简单,不需要链接其 他外部资源,或者链接可以方便地重建。
  • •抽象工厂、生成器和原型都可以用单例来实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值