我的编程空间,编程开发者的网络收藏夹
学习永远不晚

一文带你了解Java设计模式之原型模式

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

一文带你了解Java设计模式之原型模式

定义

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

原型模式其实就是从一个对象在创建另外一个可定制的对象,不需要知道任何创建的细节

解决的问题

在运行期建立和删除原型。

经常用于:

类初始化消耗资源较多

构造函数比较复杂

核心要点

1.实现cloneable 接口,重写Object的clone方法

2.利用已有的一个原型对象,快速地生成和原型对象一样的实例。

类图

浅复制与深复制的区别

浅复制:基本数据类型进行值传递、引用数据类型的指针仍是指向原来的对象(成员变量)。

深复制:基本数据类型进行值传递、引用数据类型开辟新的内存空间。

代码实现

需求:实现克隆羊

有一头羊,需要经过赋值再克隆出两头。

未使用设计模式


public class Sheep {

    private String name;

    private Integer age;

    private String color;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public String getColor() {
        return color;
    }

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

    public Sheep() {
    }

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

Main方法


public class Client {

    public static void main(String[] args) {
        //小羊
        Sheep sheep=new Sheep("小红",8,"红色");
        //克隆羊
        Sheep sheep2=sheep;
        Sheep sheep3=sheep;

        System.out.println("通过赋值,指针还是指向sheep");
        System.out.println(sheep);
        System.out.println(sheep2);
        System.out.println(sheep3);
        
    }

}

//通过赋值,指针还是指向sheep
//com.promsing.creational.prototype.type1.Sheep@1b6d3586
//com.promsing.creational.prototype.type1.Sheep@1b6d3586
//com.promsing.creational.prototype.type1.Sheep@1b6d3586

实现Cloneable接口

Cloneable是标记型的接口,它们内部都没有方法和属性,实现 Cloneable来表示该对象能被克隆,能使用Object.clone()方法。

如果没有实现 Cloneable的类对象调用clone()就会抛出CloneNotSupportedException。

实现Cloneable默认是浅复制


public class Sheep implements Cloneable {

    private String name;

    private Integer age;

    private String color;

    
    private Sheep friend;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public String getColor() {
        return color;
    }

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

    public Sheep() {
    }

    public Sheep getFriend() {
        return friend;
    }

    public void setFriend(Sheep friend) {
        this.friend = friend;
    }

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


    
    @Override
    protected Sheep clone() {

        Sheep sheep = null;
        try {
            sheep = (Sheep) super.clone();

        } catch (CloneNotSupportedException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
        return sheep;
    }
}

Main方法


public class ShallowClient {

    public static void main(String[] args) {

        Sheep sheep=new Sheep("小红",9,"红色");
        sheep.setFriend(new Sheep("小黑",10,"黑色"));
        Sheep sheep1 = sheep.clone();//开辟了新的空间
        Sheep sheep2 = sheep.clone();

        //浅复制
        System.out.println("原型羊"+sheep);
        System.out.println("克隆羊"+sheep1+"-朋友羊-"+sheep1.getFriend());
        System.out.println("克隆羊"+sheep2+"-朋友羊-"+sheep2.getFriend());
        
//原型羊com.promsing.creational.prototype.type3.Sheep@1b6d3586
//克隆羊com.promsing.creational.prototype.type3.Sheep@4554617c-朋友羊-com.promsing.creational.prototype.type3.Sheep@74a14482
//克隆羊com.promsing.creational.prototype.type3.Sheep@1540e19d-朋友羊-com.promsing.creational.prototype.type3.Sheep@74a14482


    }

}

一定要实现接口cloneable 否则报错:

Exception in thread "main" java.lang.CloneNotSupportedException: com.promsing.creational.prototype.type4.Sheep
    at java.lang.Object.clone(Native Method)
    at com.promsing.creational.prototype.type4.Sheep.clone(Sheep.java:76)
    at com.promsing.creational.prototype.type4.DeepClient.main(DeepClient.java:14)

深复制-重写clone

羊类、房子类都需要实现Cloneable接口

房子类


public class House implements Cloneable {

    //地址
    private String address;

    //尺寸
    private Integer size;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Integer getSize() {
        return size;
    }

    public void setSize(Integer size) {
        this.size = size;
    }


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

羊类


public class Sheep implements  Cloneable {

    private String name;

    private Integer age;

    private String color;

    
    private House house;

    public House getHouse() {
        return house;
    }

    public void setHouse(House house) {
        this.house = house;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public String getColor() {
        return color;
    }

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

    public Sheep() {
    }


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

    
    @Override
    protected Object clone() throws CloneNotSupportedException {

        //对基本数据类型进行处理
        Sheep deep = null;
        deep = (Sheep) super.clone();

        //对引用类型进行处理
        //进行再次克隆
        House clone = (House) deep.getHouse().clone();
        deep.setHouse(clone);

        return deep;
    }

   
}

Main


public class DeepClient {

    public static void main(String[] args) throws CloneNotSupportedException {
        Sheep sheep=new Sheep("黑",90,"heisee");
        sheep.setHouse(new House());
        Sheep clone = (Sheep)sheep.clone();
        System.out.println("原本的对象");
        System.out.println(sheep);
        System.out.println(sheep.getHouse());
        System.out.println("克隆的对象");
        System.out.println(clone);
        System.out.println(clone.getHouse());
        
        
        //开辟了新的内存空间
        //原本的对象
        //com.promsing.creational.prototype.type4.Sheep@1b6d3586
        //com.promsing.creational.prototype.type4.House@4554617c
        //克隆的对象
        //com.promsing.creational.prototype.type4.Sheep@74a14482
        //com.promsing.creational.prototype.type4.House@1540e19d
    }

}

深复制-通过对象序列化实现(推荐)

羊类、房子类都需要实现Serializable接口。注意这里可以不实现Cloneable了。

房子类


public class House implements Serializable{

    //地址
    private String address;

    //尺寸
    private Integer size;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Integer getSize() {
        return size;
    }

    public void setSize(Integer size) {
        this.size = size;
    }

}

羊类


public class Sheep implements Serializable {

    private String name;

    private Integer age;

    private String color;

    
    private House house;

    public House getHouse() {
        return house;
    }

    public void setHouse(House house) {
        this.house = house;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public String getColor() {
        return color;
    }

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

    public Sheep() {
    }


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

 
    
    public Object deepClone() {

        //创建流对象
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;

        try {

            //序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this); //当前这个对象以对象流的方式输出

            //反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            Sheep copyObj = (Sheep) ois.readObject();

            return copyObj;

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            return null;
        } finally {
            //关闭流
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            } catch (Exception e2) {
                // TODO: handle exception
                System.out.println(e2.getMessage());
            }
        }

    }
}

Main


public class DeepClient {

    public static void main(String[] args) throws CloneNotSupportedException {
        Sheep sheep=new Sheep("黑",90,"heisee");
        sheep.setHouse(new House());
        Sheep clone = (Sheep)sheep.deepClone();
        System.out.println("原本的对象");
        System.out.println(sheep);
        System.out.println(sheep.getHouse());
        System.out.println("克隆的对象");
        System.out.println(clone);
        System.out.println(clone.getHouse());
    }

}

拓展

Spring使用原型模式:@scope(“prototype”)

public static void main(String[] args) throws IOException {
      //new一个容器
    AnnotationConfigWebApplicationContext context =
        new AnnotationConfigWebApplicationContext();
    System.out.println("run success");

    OrderService bean = context.getBean(OrderService.class);
}

//根据getBean点进去
public <T> T getBean(Class<T> requiredType) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(requiredType);
}

public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
}

后续走到了。AbstractBeanFactory类中的doGetBean方法中里边代码做判断mbd.isPrototype()

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {

		String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			//代码省略~~~~
		}

		else {
			//代码省略~~~~

			
			try {
				//代码省略~~~~
                
				// Create bean instance.
                //判断是否是单例
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
                //判断是否是多例(原型)
                //这里会创建一个新的对象
				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					//代码省略~~~~
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		//代码省略~~~~
		}
		return (T) bean;
	}

ArrayList实现了Cloneable接口

public Object clone() {
    try {
        ArrayList<?> v = (ArrayList<?>) super.clone();
        v.elementData = Arrays.copyOf(elementData, size);
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}

到此这篇关于一文带你了解Java设计模式之原型模式的文章就介绍到这了,更多相关Java原型模式内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

一文带你了解Java设计模式之原型模式

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java设计模式中的原型模式讲解

原型模式是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式,今天通过本文给大家介绍下Java 原型设计模式,感兴趣的朋友一起看看吧
2023-05-18

Golang设计模式之原型模式详细讲解

如果一个类的有非常多的属性,层级还很深。每次构造起来,不管是直接构造还是用建造者模式,都要对太多属性进行复制,那么有没有一种好的方式让我们创建太的时候使用体验更好一点呢?今天的文章里就给大家介绍一种设计模式,来解决这个问题
2023-01-11

Android常用设计模式之原型模式详解

这篇文章主要为大家介绍了Android常用设计模式之原型模式详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-13

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录