原型模式(Prototype Pattern)

通过复制生成实例

1.使用背景

开发中通常通过new关键字生成实例,必须指定类名,然而在下边情况下,在 不指定类名的情况下生成实例,根据现有的实例生成新的实例。

  • 对象种类繁多,无法将其整合到同一个类中

  • 难以根据类生成实例.

    生成实例的过程太复杂,很难根据类来生成实例.比如用户想生成和之前用户生成实例完全一样的实例时,由于生成过程复杂,很难保证完全一致,所以可以保存之前的实例,然后通过复制来生成。

  • 解耦框架与生成实例


2.具体实例

在这里插入图片描述

类图:
在这里插入图片描述

Prduct

/**
 * @author Jay
 * @date 2019/6/3 22:36
 * @description 继承复制接口,定义抽象方法
 */
public interface Product extends Cloneable {
    /**
     * 使用方法
     *
     * @param s
     */
    void use(String s);
    /**
     * 定义生成实例的方法
     *
     * @return
     */
    Product createClone();
}

Manager

用接口来制定方法,则所有实现此接口的类都可以调用.添加新类时不需要再去修改方法内部.一旦使用了别的类名,将会与其他类紧密耦合在一起了。

/**
 * @author Jay
 * @date 2019/6/3 22:47
 * @description 定义注册的规范
 */
public class Manager {
    /**
     * 通过map实现一个实例池,每次调用注册方法都可以将实例放入,保证了不重复
     */
    private HashMap showcase = new HashMap();

    public void register(String name, Product proto) {
        showcase.put(name, proto);
    }

    /**
     * 定义获取实例流程,通过接口制定规范,可以接受其全部实现类对象.
     *
     * @param protoname
     * @return
     */
    public Product create(String protoname) {
        Product p = (Product) showcase.get(protoname);
        //调用复制方法,复制一个新的实例
        return p.createClone();
    }

}

MessageBox

creatClone()方法用来复制自己,若类实现复制接口或者接口继承接口,只有在本类及其子类,或者实现此接口的类中调用clone(),否则只能通过方法调用。

/**
 * @author Jay
 * @date 2019/6/3 22:58
 * @description 具体实例创建的过程
 */
public class MessageBox implements Product {
    private char decochar;

    public MessageBox(char decochar) {
        this.decochar = decochar;
    }

    @Override
    public void use(String s) {
        System.out.println(decochar + s + decochar);
    }

    @Override
    public Product createClone() {
        Product p = null;
        try {
            //只有继承了复制接口的类才可以调用此方法复制自己,将本实例n全部复制到
            //新的实例当中.
            p = (Product) clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return p;
    }
}

main

/**
 * @author Jay
 * @date 2019/6/3 23:11
 * @description
 */
public class Main {
    public static void main(String[] args) {
        //注册
        Manager m1 = new Manager();
        MessageBox m2 = new MessageBox('*');
        MessageBox m3 = new MessageBox('%');
        MessageBox m4 = new MessageBox('+');
        m1.register("星号", m2);
        m1.register("百分", m3);
        m1.register("加号", m4);
        //生成
        //父类接收,可以直接生成,不用通过new,也不需要中间复杂的生成实例过程
        Product p1 = m1.create("星号");
        p1.use("hello world");
    }
}

3.设计模式中的具体角色

Prototype(原型)

负责定义用来复制现有实例来生成新实例的方法。

ConncretePrototype(具体的原型)

继承或者实现原型,具体实现复制现有实例来生成新实例的方法,同时不同的类具体实现接口中的方法。(模板方法模式)

Client(使用者)

调用用来复制实现实例的方法,从而生成新的实例。注册生成实例池,调用复制方法复制池中已有的实例,实现生成新的对象.

在这里插入图片描述

使用类名会出现的问题:

当类作为组件复用时,一旦代码中出现要使用的类的名字,就无法与该类分离出来,无法实现代码的复用,即若要使用其他类时必须重写源码,但若是没有源码程序,只有字节码程序,则无法实现程序的修改,因此,该类能否被复用,必须是不通过修改源码也可以完成,即没有源码也可以完成复用

面向对象编程的目标之一: 作为组件的复用(.class文件)


4.clone()方法

只有实现了Cloneable接口的本类或者子类才可以调用clone(),此方法返回的是复制出的实例

clone()内部处理:

分配与要复制的实例同样大小的内存空间,将要复制的实例中的字段值复制到所分配的内存空间。

Cloneable接口是标记接口,标记此类可以复制,其中并没有clone()是object中有clone()方法。

clone()方法是浅复制

只是将复制实例的字段直接复制到新的实例中,并没有考虑字段中存的值,只会复制,并不会调用其构造函数。完全复制需要重写clone()方法,并且调用super.clone()父类方法


To GitHub

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值