设计模式快速理解原型模式,及其在源码中的应用

Posted Java鱼仔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式快速理解原型模式,及其在源码中的应用相关的知识,希望对你有一定的参考价值。

(一)什么是原型模式

在正常的开发过程中,百分之99的对象实例都是通过new进行创建的,但是在实际的场景中,还是存在一些不通过new生成对象实例的应用场景。

比如:需要生成大量类似的对象实例时,如果都通过new去创建,性能并不好。

又比如:通过很复杂的方式生成了一个对象,现在要再创建出一个类似的对象出来。

上面的两种应用场景都可以通过“拷贝”这个动作来实现,这种根据一个已有的原型对象,拷贝生成新的对象的方式,就是设计模式中的原型模式(prototype)。

在Java中,可以通过Cloneable接口和clone方法很好地实现原型模式。

(二)原型模式的简单例子

首先通过一个简单的例子让大家快速了解原型模式。

过年的时候公司给每个人发了一份邮件,这个邮件里除了署名和入职年份不一样以外,其他的内容都是相同的。比如:张三,这是你入职的第一年,祝你新年快乐XXXXX;李四,这是你入职的第二年,祝你新年快乐XXXXX。

这里的每一份邮件都可以理解为一个对象,而所有的对象实例都是相似的对象实例,因此就可以实用原型模式来拷贝生成这些重复的对象。

首先创建一个邮件对象,需要实现Cloneable接口:

public class Mail implements Cloneable
    private String name;
    private String content;
    private Integer years;
    Mail(String name,String content,Integer years)
        this.name = name;
        this.content = content;
        this.years = years;
        System.out.println("对象创建成功");
    
    private void showMail()
        System.out.println(name+",这是你入职的第"+years+"年,"+content);
    

    @Override
    protected Object clone() throws CloneNotSupportedException 
        System.out.println("拷贝成功");
        return super.clone();
    

    public void setContent(String content) 
        this.content = content;
    

    public void setName(String name) 
        this.name = name;
    

    public void setYears(Integer years) 
        this.years = years;
    

接下来在使用的时候先通过new创建一个基础对象实例,其他的均通过clone进行拷贝:

public static void main(String[] args) throws CloneNotSupportedException 
    Mail mail = new Mail("张三", "祝你新年快乐XXXXXX", 1);
    mail.showMail();
    Mail cloneMail = (Mail) mail.clone();
    cloneMail.setName("李四");
    cloneMail.setYears(2);
    mail.showMail();

这样一个简单的原型模式就实现了。

(三)基于管理器的原型模式

上面的例子可以增加对原型模式的理解,在实际开发中,更常用的是使用一个管理器去管理原型对象,可以在管理器类中通过一个HashMap保存原型对象。以水果店为例子。

首先定义了一个接口叫做Fruit,里面有两个方法:,shape方法用于展示水果的外观,createFruit方法用于通过克隆创建原型对象实例。

public interface Fruit extends Cloneable
    void shape();
    Object createFruit() throws Exception;

接着定义管理器,管理器由HashMap进行管理,提供注册和创建实例的功能:

public class FruitManager 
    private HashMap<String,Fruit> managerMap = new HashMap<>();
    public void register(String name,Fruit fruit)
        managerMap.put(name,fruit);
    
    public Fruit create(String name) throws Exception
        Fruit fruit = managerMap.get(name);
        return (Fruit) fruit.createFruit();
    

下一步就是定义两个具体的对象,需要注意的是createFruit()方法使用了clone()进行拷贝:

public class Apple implements Fruit
    @Override
    public void shape() 
        System.out.println("苹果是红色的圆形水果");
    
    @Override
    public Object createFruit() throws Exception 
        return super.clone();
    


public class Orange implements Fruit
    @Override
    public void shape() 
        System.out.println("橘子是黄色的圆形水果");
    
    @Override
    public Object createFruit() throws Exception
        return super.clone();
    

最后写一个测试方法:

public static void main(String[] args) throws Exception 
    FruitManager manager = new FruitManager();
    //注册到管理器中
    manager.register("apple",new Apple());
    manager.register("orange",new Orange());
    //通过create方法不断拷贝新的对象
    Fruit apple = manager.create("apple");
    apple.shape();
    Fruit orange = manager.create("orange");
    orange.shape();

(四)原型模式在源码中的应用

其实在很多地方都用到了原型模式,比如最常用的ArrayList,同样定义了clone方法供调用者进行拷贝。

抛去Cloneable相关的接口,一些对象之间的复制操作也是原型模式的实践,比如Spring里BeanUtils.copyProperties()这个方法,同样实现了根据一个已有的原型对象,拷贝生成新的对象。

(五)总结

本章内容主要通过两个例子讲解了原型模式的概念以及应用,我是鱼仔,我们下期再见!

以上是关于设计模式快速理解原型模式,及其在源码中的应用的主要内容,如果未能解决你的问题,请参考以下文章

设计模式快速理解原型模式,及其在源码中的应用

设计模式快速理解建造者模式,及其在JDK源码中的应用

快速理解工厂方法模式,及其在源码中的应用

快速理解工厂方法模式,及其在源码中的应用

设计模式快速理解建造者模式,及其在JDK源码中的应用

设计模式快速理解建造者模式,及其在JDK源码中的应用