美文网首页
设计模式——原型模式

设计模式——原型模式

作者: 烟雾袅绕 | 来源:发表于2018-09-18 15:29 被阅读12次
简介:
  • 原型模式是一个创建型的模式。
  • 通过给出一个原型对象来指明所创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。
  • 原型模式要求对象实现一个可以“克隆”自身的接口,这样就可以通过复制一个实例对象本身来创建一个新的实例,这样一来,通过原型实例创建新的对象,就不再需要关心这个实例本身的类型,只要实现了克隆自身的方法,就可以通过这个方法来获取新的对象,而无须再去通过new来创建。
使用场景
  1. 原型模式多用于创建复杂的或者构造耗时的实例,因为这种情况下,复制一个已经存在的实例可使程序运行更高效。
  2. 通过new产生的一个对象需要非常繁琐的数据准备或者权限,这时可以使用原型模式。
  3. 个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。
原型模式的参与角色
  1. 客户角色:客户类提出创建对象的请求。
  2. 抽象原型角色:这是一个抽象角色,通常由一个java接口或抽象类实现,具体原型都需要实现该接口。
  3. 具体原型角色:客户端所需要的被复制的对象。
实例演示
/**
 *
 * @ Description:Cloneable 扮演抽象原型角色  Book 扮演具体原型角色,当然也可以设成抽象原型角色,由其他具体对象来实现
 * @Version: $version$
 */
public class Book implements  Cloneable {

    private   String title;

    private ArrayList<String> images = new ArrayList<String>();


    @Override
    protected Object clone() throws CloneNotSupportedException {
       Book book = (Book) super.clone();
       return  book;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public ArrayList<String> getImages() {
        return images;
    }

    public void setImages(String images) {
        this.images.add(images);
    }
    public void showBook() {
        System.out.println("----------------------Start----------------------");

        System.out.println("title:" + title);
        for (String img : images) {
            System.out.println("image name:" + img);
        }

        System.out.println("----------------------End----------------------");
    }
}
客户角色
public class Client {

    public static void main(String[] args) {
        // 1.构建书本对象
        Book book1 = new Book();        
        // 2.编辑书本,添加图片
        book1.setTitle("书1");
        book1.addImage("图1");
        book1.showBook();

        // 以原型文档为原型,拷贝一份副本
        Book book2 = (Book) book1.clone();
        book2.showBook();
        // 修改图书副本,不会影响原始书本
        book2.setTitle("书2");
        book2.showBook();

        // 再次打印原始书本
        book1.showBook();
    }
}

输出
----------------------Start----------------------
title:书1
image name:图1
----------------------End----------------------
----------------------Start----------------------
title:书1
image name:图1
----------------------End----------------------
----------------------Start----------------------
title:书2
image name:图1
----------------------End----------------------
----------------------Start----------------------
title:书1
image name:图1
----------------------End----------------------
备注:

book2是book的一份拷贝,它和book1的内容是一样的。而book2修改了“标题”-字符串(基本的数据类型),并不影响book1的标题,这就保证了book1的安全性。

浅拷贝引用
public class Client {

    public static void main(String[] args) {
        // 1.构建书本对象
        Book book1 = new Book();        
        // 2.编辑书本,添加图片
        book1.setTitle("书1");
        book1.addImage("图1");
        book1.showBook();

        // 以原型文档为原型,拷贝一份副本
        Book book2 = (Book) book1.clone();
        book2.showBook();
        // 修改图书副本,不会影响原始书本
        book2.setTitle("书2");
        book2.addImage("图2");
        book2.showBook();

        // 再次打印原始书本
        book1.showBook();
    }
}
输出
----------------------Start----------------------
title:书1
image name:图1
----------------------End----------------------
----------------------Start----------------------
title:书1
image name:图1
----------------------End----------------------
----------------------Start----------------------
title:书2
image name:图1
image name:图2
----------------------End----------------------
----------------------Start----------------------
title:书1
image name:图1
image name:图2
----------------------End----------------------
备注

最后两个书本内容输出是一致的。引用类型的新对象book2的image只是单纯指向了this.image引用,并没有重新构造一个image对象,然后将原始书本的图片添加到新的image对象中,这样导致book2中的image与原始书本中的是同一个对象。因此,修改其中一个书本的图片,另一个书本也会受到影响。
  如何解决?因为Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、集合、容器对象、引用对象等都不会拷贝;所以采用深拷贝。

深拷贝应用
/**
     * 重写拷贝方法
     */
    @Override
    protected Book clone()  {
        try {
            Book book = (Book) super.clone();
            // 对image对象也调用clone()函数,进行拷贝
            book.image = (ArrayList<String>) this.image.clone();
            return book;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
输出
----------------------Start----------------------
title:书1
image name:图1
----------------------End----------------------
----------------------Start----------------------
title:书1
image name:图1
----------------------End----------------------
----------------------Start----------------------
title:书2
image name:图1
image name:图2
----------------------End----------------------
----------------------Start----------------------
title:书1
image name:图1
----------------------End----------------------
备注

将book.image指向this.image的一份拷贝,而不是this.image本身,实现了完全的拷贝,这样再互不影响。

相关文章

网友评论

      本文标题:设计模式——原型模式

      本文链接:https://www.haomeiwen.com/subject/gobogftx.html