探索原型模式的核心概念

原型模式

原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。(这种不通过new关键字来产生一个对象,而是通过对象复制来实现的模式。)

原型模式结构

在这里插入图片描述

  1. 原型(Prototype)接口将对克隆方法进行声明。在绝大多数情况下,其中只会有一个名为 clone克隆的方法。

  2. 具体原型(Concrete Prototype)类将实现克隆方法。除了将原始对象的数据复制到克隆体中之外,该方法有时还需处理克隆过程中的极端情况,例如克隆关联对象和梳理递归依赖等等。

  3. 客户端(Client)可以复制实现了原型接口的任何对象。

  • 原型注册表

    原型注册表提供了一种访问常用原型的简单方法,其中存储了一系列可供随时复制的预生成对象。

    新建一个工厂类来实现注册表, 或者在原型基类中添加一个获取原型的静态方法。 该方法必须能够根据客户端代码设定的条件进行搜索。 搜索条件可以是简单的字符串, 或者是一组复杂的搜索参数。 找到合适的原型后, 注册表应对原型进行克隆, 并将复制生成的对象返回给客户端。

    在这里插入图片描述

通用代码结构示例:

public class PrototypeClass implements Cloneable{
	
	@Override 
	public PrototypeClass clone(){
		PrototypeClass prototypeClass = null;
		try{
			prototypeClass = (PrototypeClass)super.clone();
		} catch (CloneNotSupportedException e){
			//异常处理
		}
		return prototypeClass;
	}
}

原型模式应用场景

  • 如果你需要复制一些对象,同时又希望代码独立于这些对象所属的具体类,可以使用原型模式。

    原型模式为客户端代码提供一个通用接口, 客户端代码可通过这一接口与所有实现了克隆的对象进行交互, 它也使得客户端代码与其所克隆的对象具体类独立开来。

  • 如果子类的区别仅在于其对象的初始化方式, 那么你可以使用该模式来减少子类的数量。 别人创建这些子类的目的可能是为了创建特定类型的对象。

    在原型模式中,你可以使用一系列预生成的、各种类型的对象作为原型。客户端不必根据需求对子类进行实例化,只需找到合适的原型并对其进行克隆即可。

在这里插入图片描述

**识别方法:**原型可以简单地通过 clonecopy等方法来识别。

原型模式优缺点

优点:

  • 你可以克隆对象,而无需与它们所属的具体类相耦合。

  • 你可以克隆预生成原型,避免反复运行初始化代码。

  • 你可以更方便地生成复杂对象。

  • 你可以用继承以外的方式来处理复杂对象的不同配置。

缺点

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

练手题目

题目描述

公司正在开发一个图形设计软件,其中有一个常用的图形元素是矩形。设计师在工作时可能需要频繁地创建相似的矩形,而这些矩形的基本属性是相同的(颜色、宽度、高度),为了提高设计师的工作效率,请你使用原型模式设计一个矩形对象的原型。使用该原型可以快速克隆生成新的矩形对象。

输入描述

首先输入一个字符串,表示矩形的基本属性信息,包括颜色、长度和宽度,用空格分隔,例如 “Red 10 5”。然后输入一个整数 N(1 ≤ N ≤ 100),表示使用原型创建的矩形数量。

输出描述

对于每个矩形,输出一行字符串表示矩形的详细信息,如 “Color: Red, Width: 10,Height: 5”。

在这里插入图片描述

提示信息

使用原型模式中的克隆方法实现矩形对象的创建。

题解:

原型模式解法:

import java.util.Scanner;
import java.io.*;

// 抽象类 Shape,表示形状的基类,原型模式
abstract class Shape{
    protected int height ;
    protected int width ;
    protected String color ;
    
    public Shape(){}
    public Shape(int height,int width, String color){
        this.height = height;
        this.width = width;
        this.color = color;
    }
    
    public abstract Shape clone();
    
    //get、set方法
    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
    
}

class Rectangle extends Shape{
    
    public Rectangle(int height,int width, String color){
        super(height, width, color);
    }
    
    @Override
    public Shape clone(){
        return new Rectangle(this.height, this.width, this.color);
    }
    
}

public class Main{
    public static void main (String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        String[] parts = input.split(" ");
        
        if (parts.length == 3){
            String color = parts[0];
            int width ,height;
            try{
                width = Integer.parseInt(parts[1]);
                height = Integer.parseInt(parts[2]);
                Shape shape = new Rectangle(height,width ,color);
                int num = scanner.nextInt();
                
                for (int i=0 ;i<num;i++ ){
                    Shape clonedShape =shape.clone();
                    System.out.println("Color: "+color+", Width: "+width+", Height: "+ height);
                } 
                
            }catch(NumberFormatException e){
                    System.out.println("输入错误,请重新输入");
            }
        } else {
            System.out.println("输入格式错误,请按格式输入:颜色 宽度 高度");
        }
         scanner.close(); 
        
    }
}

使用原型注册表来实现

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

// 原型模式抽象类Shape,表示形状的基类
abstract class Shape {
    protected int height;
    protected int width;
    protected String color;

    public Shape() {}

    public Shape(int height, int width, String color) {
        this.height = height;
        this.width = width;
        this.color = color;
    }
    
    // 抽象方法 clone,用于克隆形状
    public abstract Shape clone();
    
    //get、set方法。
    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
}

// Rectangle 类,继承自 Shape 表示矩形
class Rectangle extends Shape {
    public Rectangle(int height, int width, String color) {
        super(height, width, color);
    }
    
    // 克隆方法,返回一个新的矩形对象
    @Override
    public Shape clone() {
        return new Rectangle(this.height, this.width, this.color);
    }
}

// 原型注册表类,用于存储和管理形状
class ShapeRegistry {
    private Map<String, Shape> shapeMap = new HashMap<>();
    
    // 注册形状,使用形状 ID 作为键
    public void registerShape(String shapeId, Shape shape) {
        shapeMap.put(shapeId, shape);
    }
    // 获取形状,通过克隆返回一个新的对象
    public Shape getShape(String shapeId) {
        Shape shape = shapeMap.get(shapeId);
        return shape != null ? shape.clone() : null;
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        ShapeRegistry shapeRegistry = new ShapeRegistry();

        // 注册一个默认的矩形形状
        shapeRegistry.registerShape("defaultRectangle", new Rectangle(10, 20, "red"));
        
        String input = scanner.nextLine();
        String[] parts = input.split(" ");
        if (parts.length == 3) {
            String color = parts[0];
            try {
                int width = Integer.parseInt(parts[1]);
                int height = Integer.parseInt(parts[2]);
                    
                //创建并注册一个新的矩形
                Shape newRectangle = new Rectangle(height, width, color);
                shapeRegistry.registerShape("userRectangle", newRectangle);
                    
                int num = scanner.nextInt();
                for (int i = 0; i < num; i++) {
                    Shape clonedShape = shapeRegistry.getShape("userRectangle");
                    if (clonedShape != null) {
                        System.out.println("Color: " + clonedShape.getColor() + 
                                 ", Width: " + clonedShape.getWidth() + 
                                ", Height: " + clonedShape.getHeight());
                    } else {
                        System.out.println("在注册表中找不到形状.");
                    }
                }
            } catch (NumberFormatException e) {
                System.out.println("输入错误,请重新输入.");
            }
        } else {
            System.out.println("输入格式错误,请按格式输入:颜色 宽度 高度.");
        }
        scanner.close();
    }
}
  • 29
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天马行空的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值