原型模式—创建型

创建型

1,单例设计模式
2,工厂设计模式
3,建造者设计模式
4,原型设计模式

结构型

5,代理设计模式
6,桥接设计模式
7,装饰设计模式
8,适配器设计模式
9,外观设计模式
10,享元设计模式
11,组合设计模式

行为型

12,模板设计模式

简介:

原型二字说明了该模式应该有一个样板实例,用户从这个样板对象复制(克隆)出一个内部属性一致的对象。被复制的实例就是原型。如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同),在这种情况下,我们可以利用对已有对象(原型)进行复制(或者叫拷贝)的方式来创建新对象,以达到节省创建时间的目的。这种基于原型来创建对象的方式就叫作原型设计模式(Prototype Design Pattern),简称原型模式。

应用场景

1,类初始化需要很消耗资源,通过原型复制创建对象,可以避免这些资源消耗;

2,通过new创建一个对象需要很繁琐的数据准备,可通过原型模式;

3,一个类的不同对象之间差别不大,大部分字段都相同;

实现

对于熟悉 JavaScript 语言的前端程序员来说,原型模式是一种比较常用的开发模式。这是因为,有别于 Java、C++ 等基于类的面向对象编程语言,JavaScript 是一种基于原型的面向对象编程语言。在Java语言中,最简单的实现就是调用的clone()方法;

案例:

原型

Book.class为原型,复制出更多的Book对象;

import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;

public class Book implements Cloneable{

    private String name;
    private ArrayList<String> mImages = new ArrayList<>();

    public String getName() {
        return name;
    }

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

    public List<String> getImages() {
        return mImages;
    }

    public void setImage(String image) {
        this.mImages.add(image);
    }

    public void showConten() {
        System.out.println("**************** Start **************");
        System.out.println("name: "+ this.name);

        for (String img : mImages) {
            System.out.println("image name: " + img);
        }
        System.out.println("**************** End **************");
    }

    @NonNull
    @Override
    protected Book clone() {
        try {
            Book book = (Book) super.clone();
            book.name = this.name;
            book.mImages = this.mImages;
            return book;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

复制对象

public class CloneBook {

    public static void main(String[] args) {
        Book book = new Book();
        book.setName("活法");
        book.setImage("图1");
        book.setImage("图2");

        book.showConten();

        Book book1 = book.clone();
        book1.setName("Android");
        book1.showConten();

        book.showConten();
    }
}

 运行:

**************** Start **************
name: 活法
image name: 图1
image name: 图2
**************** End **************
**************** Start **************
name: Android
image name: 图1
image name: 图2
**************** End **************
**************** Start **************
name: 活法
image name: 图1
image name: 图2
**************** End **************
 

浅拷贝和深拷贝

原型模式有两种实现方法,深拷贝和浅拷贝。不管浅拷贝还是深拷贝都是原型模式的实现方式;

浅拷贝:浅拷贝只会复制对象中基本数据类型数据和引用对象的内存地址,不会递归地复制引用对象,以及引用对象的引用对象;

上面的Book对象的拷贝就是浅拷贝,不信可以试试,代码如下

public class CloneBook {

    public static void main(String[] args) {
        Book book = new Book();
        book.setName("活法");
        book.setImage("图1");
        book.setImage("图2");

        book.showConten();

        Book book1 = book.clone();
        book1.setName("Android");
        book1.setImage("图3");//修改引用对象的数据
        book1.showConten();

        book.showConten();
    }
}

 运行结果:

**************** Start **************
name: 活法
image name: 图1
image name: 图2
**************** End **************
**************** Start **************
name: Android
image name: 图1
image name: 图2
image name: 图3
**************** End **************
**************** Start **************
name: 活法
image name: 图1
image name: 图2
image name: 图3
**************** End **************

可以看出拷贝的对象book1修改了原型中的引用对象的数据(mImages),结果book对象中的引用对象的数据也改变了;book和book1同时指向mImages的同一个对象地址;

深拷贝:深拷贝得到的是一份完完全全独立的对象。

修改Book类中的clone方法

@NonNull
@Override
protected Book clone() {
     try {
         Book book = (Book) super.clone();
         book.name = this.name;
         book.mImages = (ArrayList<String>) this.mImages.clone();
         return book;
     } catch (CloneNotSupportedException e) {
         e.printStackTrace();
     }
     return null;
}

重新运行如下代码

public class CloneBook {

    public static void main(String[] args) {
        Book book = new Book();
        book.setName("活法");
        book.setImage("图1");
        book.setImage("图2");

        book.showConten();

        Book book1 = book.clone();
        book1.setName("Android");
        book1.setImage("图3");//修改引用对象的数据
        book1.showConten();

        book.showConten();
    }
}

结果:book1修改了引用类型对象中的数据,对book没有任何影响;这就是深拷贝;

**************** Start **************
name: 活法
image name: 图1
image name: 图2
**************** End **************
**************** Start **************
name: Android
image name: 图1
image name: 图2
image name: 图3
**************** End **************
**************** Start **************
name: 活法
image name: 图1
image name: 图2
**************** End **************

猜你喜欢

转载自blog.csdn.net/ezconn/article/details/106754096