【设计模式-2】原型模式的原理、代码实现及类图展示

 我们一定对类的实例化比较熟悉,前面我们说的单例、还有3种工厂模式都是通过new关键字来创建对象,下面我们来了解一种新的对象创建的方式。

1. 定义

 原型模式也是一种创建型的设计模式,实现和原理总体比较简单,一句话总结呢,就是可以实现用已有的对象创建新的对象,而不是用类来实例化对象,这样可以起到提升效率的目的。

 众所周知,类的实例化可以创建对象,但其实这是一个比较耗时耗力的工作,尤其是在大量实例化对象的业务场景下,可能会对系统的性能造成很大的影响。这时候,原型模式就可以很好的解决问题,用已有的对象来生成对象的副本,这里已有的对象就是原型对象,副本对象就是拷贝对象。这样对于那些有非常复杂的初始化的操作,或者是需要消耗大量资源的情况,原型模式的优势就体现出来了。

2. 代码实现

 我们来举一个飞机大战的游戏例子,游戏的场是在手机屏幕上方,飞下来很多敌机,而我方战机只有一架,其中敌机的飞行轨迹必须是呈上下直线型的,我方战机可以上下左右移动。因为本篇我们学习原型模式,所以重点关照的是敌机,我方战机其实可以通过前面讲的单例模式实现。

2.1 实例化方式

 假设游戏过程有500架敌机出现,通常情况下,使用实例化创建对象的方式,代码实现可以这样。

java 复制代码
public class EnemyPlain {
    // x坐标
    private int x;
    // y坐标
    private int y;
    // 敌机固定x坐标,只能上下移动
    public EnemyPlain(int x) {
        this.x = x;
    }
    public int getX() {
        return x;
    }
    public int getY() {
        return y;
    }
    // 手柄每调用一次setY方法,Y坐标加一
    public void setY() {
        y ++ ;
    }
}

 客户端获取敌机的方法如下:

java 复制代码
public class Client {
    public static void main(String[] args) {
        // 500架敌机集合
        List<EnemyPlain> enemyPlains = new ArrayList<>();
        // 实例化500架敌机
        for (int i = 0; i < 500; i++) {
            // 随机出现在0~200的坐标内
            EnemyPlain enemyPlain = new EnemyPlain(RandomUtil.randomInt(200));
            enemyPlains.add(enemyPlain);
        }
    }
}

 这种代码实现的方式是很常见的,但要命的是这500个对象在客户端初始化的时候就会被创建出来,500个对象会占用大量的堆内存空间,这还是定义的对象只有两个属性的前提下。另外,CPU本身就是很宝贵的资源,一次性实例化500个对象,本身也会消耗系统很大的系统资源,极端的情况下会造成游戏界面卡顿,造成不友好的用户体验,下面我们用原型模式来试一下。

2.2 原型模式

 原型模式的代码实现,首先把原型类实现java.lang.Clone接口,接着实现 clone()方法。

java 复制代码
// 1.实现java.lang.Clone接口
public class EnemyPlain implements Cloneable {
    // x坐标
    private int x;
    // y坐标
    private int y;
    // 敌机固定x坐标,只能上下移动
    public EnemyPlain(int x) {
        this.x = x;
    }
    public int getX() {
        return x;
    }
    public int getY() {
        return y;
    }
    // 手柄每调用一次setY方法,Y坐标加一
    public void setY() {
        y ++ ;
    }
    public void setX(int x) {
        this.x = x;
    }
    // 重写克隆 clone 方法
    @Override
    public EnemyPlain clone() throws CloneNotSupportedException {
        return (EnemyPlain)super.clone();
    }
}

 客户端获取原型拷贝副本代码实现:

java 复制代码
public class ClientAno {
    public static void main(String[] args) throws CloneNotSupportedException {
        // 创建原型对象
        EnemyPlain enemyPlain = new EnemyPlain(100);
        // 存放500架敌机
        List<EnemyPlain> list = new ArrayList<>();
        // 克隆500架敌机
        for (int i = 0; i < 500; i++) {
            EnemyPlain clonePlain = enemyPlain.clone();
            // 设置横坐标
            clonePlain.setX(RandomUtil.randomInt(200));
            list.add(clonePlain);
        }
    }
}

 这里需要特别说明,clone()方法并不是从Cloneable接口实现来的,而是继承自java.lang.Object对象。另外,一般在获取克隆对象的时候,可以借助工厂模式一块实现。

3. UML类图

 下面,就以上面飞机大战这个游戏的这个例子,画一个原型模式的UML类图。

相关推荐
范中勤15 小时前
技术文档:模型工厂 `llm_provider` / `llm_use` 分层设计
设计模式·langchain·架构设计·模型工厂·llm_provider
浅尝辄止;17 小时前
设计模式在HIS/LIS医疗系统中的完整实践指南(C#版)
开发语言·设计模式·c#
范中勤17 小时前
适配器模式(Adapter Pattern):原理、场景与 LLM 多厂商工程落地
设计模式·架构·langchain·适配器模式·多厂商
408高手1 天前
23种设计模式
设计模式
沫璃染墨1 天前
《Linux工程实践篇(二):线程池实战——从线程安全单例到完整源码实现》
linux·开发语言·c++·单例模式·设计模式·系统架构
sarasuki2 天前
MCP 为什么是一个协议而不是一个框架呢?
设计模式·agent·mcp
geovindu2 天前
rust: Borg Pattern(续)
开发语言·后端·设计模式·rust·博格模式
染指11102 天前
140.Agent-多Agent框架-Agent执行Skills流程
数据库·人工智能·设计模式·langchain·agents
sarasuki3 天前
Agent 是怎么做错误处理的呢?
人工智能·设计模式·agent
A1Book3 天前
从 0 设计历史专题资料汇编的 AI Agent 编排架构——六轮真实任务复盘
设计模式