原型设计模式以及在 Spring 中的使用

前文:

设计模式的七大原则

单例模式

编写一个接口,实现代理设计模式

迭代器模式

工厂模式

Spring的入门(概述)

Bean的相关配置以及Spring的配置

p名称空间的属性注入、集合属性的注入以及Spring分模块配置


在介绍原型设计模式之前先看下下面这段代码

定义一个 Sheep 类

package com.java.springtest.prototype;

public class Sheep {
    private String name;
    private int age;
    private String color;

    public Sheep(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", color='" + color + '\'' +
                '}';
    }
}

客户端

package com.java.springtest.prototype;

public class Client {
    public static void main(String[] args) {
        Sheep sheep = new Sheep("Tom",1,"White");
        Sheep sheep2 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep3 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep4 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep5 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep6 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep7 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep8 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep9 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep10 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());

        System.out.println(sheep);
        System.out.println(sheep2);
        System.out.println(sheep3);
        System.out.println(sheep4);
        System.out.println(sheep5);
        System.out.println(sheep6);
        System.out.println(sheep7);
        System.out.println(sheep8);
        System.out.println(sheep9);
        System.out.println(sheep10);
    }
}

输出:
在这里插入图片描述
这段代码很好理解,就是创建 10 个 对象,分别打印

传统方式解决克隆羊的优缺点

  • 优点是比较好理解,简单且易操作
  • 在创建新的对象时,总是需要重新获取原始对象的属性,如果创建的对象比较复杂时,效率较低
  • 总是需要重新初始化对象,而不是动态地获得对象运行时的状态,不够灵活

改进的思路: 在 Java 中 Object 类是所有类的父类,Object 类提供了一个 clone() 方法,该方法可以将一个 Java 对象复制一份,但是需要实现 clone() 的 Java 类必须实现一个接口 Cloneable,该接口表示该类能够复制且具有复制的能力 =》 原型模式

原型模式

基本介绍

  • 原型模式是指:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象
  • 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节
  • 工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建,即 对象的 clone()

举例

将上述的 Sheep 修改为如下:

package com.java.springtest.prototype;

public class Sheep implements Cloneable {
    private String name;
    private int age;
    private String color;

    public Sheep(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", color='" + color + '\'' +
                '}';
    }

    // 克隆该实例,使用默认的 clone 方法来完成
    @Override
    protected Object clone() {
        Sheep sheep = null;
        try {
            sheep = (Sheep) super.clone();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return sheep;
    }
}

客户端

package com.java.springtest.prototype;

public class Client {
    public static void main(String[] args) {
        System.out.println("原型模式完成对象的创建");
        Sheep sheep = new Sheep("Tom",1,"White");
        Sheep sheep2 = (Sheep) sheep.clone();
        Sheep sheep3 = (Sheep) sheep.clone();
        Sheep sheep4 = (Sheep) sheep.clone();
        Sheep sheep5 = (Sheep) sheep.clone();
        Sheep sheep6 = (Sheep) sheep.clone();
        Sheep sheep7 = (Sheep) sheep.clone();
        Sheep sheep8 = (Sheep) sheep.clone();
        Sheep sheep9 = (Sheep) sheep.clone();
        Sheep sheep10 = (Sheep) sheep.clone();

        System.out.println(sheep);
        System.out.println(sheep2);
        System.out.println(sheep3);
        System.out.println(sheep4);
        System.out.println(sheep5);
        System.out.println(sheep6);
        System.out.println(sheep7);
        System.out.println(sheep8);
        System.out.println(sheep9);
        System.out.println(sheep10);
    }
}

输出:
在这里插入图片描述

原型模式在 Spring 框架中的应用

在 Spring 中原型 bean 的创建,就是使用得原型设计模式

比如我们在配置 Spring 的 bean 的时候,有这么个标签, 而这个 scope 是用来区分你要设置的是单例的还是原型的,用过 Spring 的朋友应该都知道 Spring 的 bean 默认是单例的,不熟悉 Spring 的朋友可以看下我之前写的文章 Bean的相关配置以及Spring的配置

<bean id="sheep" class="com.java.springtest.prototype.Sheep" scope="prototype"/>

这里的 class 指向的就是我们上述的 Sheep 类

然后我们创建一个测试类来读取一下这个配置文件

package com.java.springtest.testdemo;

import com.java.springtest.prototype.Sheep;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author Woo_home
 * @create by 2020/2/17
 */
public class PrototypeTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
        Sheep sheep = (Sheep) applicationContext.getBean("sheep");
        System.out.println(sheep);
    }
}

输出:
在这里插入图片描述
为了更好地理解 Spring 是如何使用原型设计模式的,我们需要探究一下源码,我们在 getBean() 这行打个断点调试一下:
在这里插入图片描述
点击下一步的时候跳转到了 AbstractApplicationContext 类的 getBean() 方法
在这里插入图片描述
但是这还看不出是否使用了原型,继续往下执行
上面的图中通过 this.getBeanFactory().getBean(name) 调用了 getBean() 方法
该 getBean() 方法是 AbstractBeanFactory 类的 public Object getBean(Stirng name) 方法
在这里插入图片描述
从图中可以看到 getBean() 方法调用的是 doGetBean() 方法,继续执行

跳转到了 doGetBean() 方法,该方法使用了泛型
在这里插入图片描述
而我们要的东西就在这个方法里面,我们把代码拉到下面一点有这么一段代码

这段代码很容易理解,判断当前是否为单例,如果是则调用 createBean() 创建一个单例实例,但是我们在 bean 中定义的是 prototype 原型,所以代码并不会执行 if 里面的语句
在这里插入图片描述而在 if 后面有个 else 语句,否则如果是原型的则调用 createBean() 创建一个原型的实例
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值