【设计模式-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类图。

相关推荐
晨米酱3 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机8 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机9 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机9 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机9 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤9 小时前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机1 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴1 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript
李广坤1 天前
工厂模式
设计模式