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

相关推荐
杨充4 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充4 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充4 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充5 小时前
2.面向对象的特性
设计模式
杨充5 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充5 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充5 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯8 小时前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯16 小时前
GoF设计模式——解释器模式
java·后端·spring·设计模式