• 原型模式


    什么是原型模式

    克隆

    原型模式是一个创建型的模式。原型二字表明了改模式应该有一个样板实例,用户从这个样板对象中复制一个内部属性一致的对象,这个过程也就是我们称的“克隆”。被复制的实例就是我们所称的“原型”,这个原型是可定制的。原型模式多用于创建复杂的或者构造耗时的实例,因为这种情况下,复制一个已经存在的实例可使程序运行更高效。

    原型模式应用场景

    (1)   类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等,通过原型拷贝避免这些消耗。 
    (2)通过new产生的一个对象需要非常繁琐的数据准备或者权限,这时可以使用原型模式。 
    (3)一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。

    Spring框架中的多例就是使用原型。

    原型模式UML类图(通用)

    原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。Prototype类需要具备以下两个条件: 
      (1)实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。 
      (2)重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此Prototype类需要将clone方法的作用域修改为public类型。

     

    Spring可以设置单例 多例(原型)本质上使用克隆技术

    VO DTO 深浅 拷贝

    克隆的对象先创建成功后 才可以创建  

     

    废话不多说,上手敲:

    要实现克隆的这个类 必须实现接口!然后重写方法!

    package YuanXingModel;
    
    
    import java.util.ArrayList;
    import java.util.List;
    //定义一个被克隆的类 这个类必须实现 Cloneable接口
    public class Book implements Cloneable{
    
        private String title;  //书题目
        private ArrayList<String> imgs = new ArrayList<>();  //书里面的图片
        private int num;
    
        public int getNum() {
            return num;
        }
        public void setNum(int num) {
            this.num = num;
        }
        public List<String> getImgs() {
            return imgs;
        }
        public void setImgs(ArrayList<String> imgs) {
            this.imgs = imgs;
        }
        public String getTitle() {
            return title;
        }
        public void setTitle(String title) {
            this.title = title;
        }
        
        //封装一个方法
        public void addImg(String imgName) {
            imgs.add(imgName);
            
        }
        
        public void showBook(){   //展示下
            System.out.println("title是"+title);
            System.out.println("num是"+num);
            for(String img : imgs){
                System.out.println("img是"+img);
            }    
        }
        
        @Override
        protected Object clone() throws CloneNotSupportedException {
           //默认浅克隆   基本类型克隆了 引用类型没有克隆
             Book book = (Book)super.clone();   //做一个强转  
    //            book.imgs =(ArrayList<String>)this.imgs.clone(); //再克隆一个 复制给新的  属性克隆
            //this.title.clone()  String是没有的! 大家可以试试!Stirng没有克隆方法哟 final类型的  
            return book;
        }
        
    }

    客户端:

    package YuanXingModel;
    
    public class Client {
    
        public static void main(String[] args) {
    
                Book book1 = new Book();
                book1.setTitle("算法导论");
                book1.addImg("图1");
                book1.addImg("图2");
                book1.setNum(300);
                book1.showBook();
                System.out.println("#############################");
            // 克隆一个 以原型方式进行复制
            try {
                Book book2 = (Book) book1.clone();
                book2.setTitle("设计模式");
                book2.addImg("图片A");
                book2.addImg("图片B");
                book2.setNum(900);
                book2.showBook();
                System.out.println(book1==book2);
                 System.out.println("#############################");
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
             System.out.println("#############################");
            book1.showBook();  //再看看以前的
            
        }
    }

    运行结果:

    book2修改了 会影响到book1   浅拷贝:只会拷贝基本类型,不会拷贝引用类型    原理 跟 之后的 都是《算法导论》  再打印时候 不是 《设计模式》  

    此时可以打印下 book1 和 book2 的地址是否相同  运行结果是false    两个对象的内存地址是不一样的

     而引用类型复制之后,还是共同引用的! 看上面的图就OK啦。 基本数据类型是不会这样的 

     String 被final 修饰了 不能被更改了  

     深克隆,开辟新的内存地址。需要这么修改:

    package YuanXingModel;
    
    
    import java.util.ArrayList;
    import java.util.List;
    //定义一个被克隆的类 这个类必须实现 Cloneable接口
    public class Book implements Cloneable{
    
        private String title;  //书题目
        private ArrayList<String> imgs = new ArrayList<>();  //书里面的图片
        private int num;
    
        public int getNum() {
            return num;
        }
        public void setNum(int num) {
            this.num = num;
        }
        public List<String> getImgs() {
            return imgs;
        }
        public void setImgs(ArrayList<String> imgs) {
            this.imgs = imgs;
        }
        public String getTitle() {
            return title;
        }
        public void setTitle(String title) {
            this.title = title;
        }
        
        //封装一个方法
        public void addImg(String imgName) {
            imgs.add(imgName);
            
        }
        
        public void showBook(){   //展示下
            System.out.println("title是"+title);
            System.out.println("num是"+num);
            for(String img : imgs){
                System.out.println("img是"+img);
            }    
        }
        
        @Override
        protected Object clone() throws CloneNotSupportedException {
           //默认浅克隆   基本类型克隆了 引用类型没有克隆
             Book book = (Book)super.clone();   //做一个强转  
                book.imgs =(ArrayList<String>)this.imgs.clone(); //再克隆一个 复制给新的  属性克隆
            //this.title.clone()  String是没有的! 大家可以试试!Stirng没有克隆方法哟 final类型的  
            return book;
        }
        
    }

    运行结果:

     总结一点 String 不会产生引用关系 是直接复制过来的 跟 基本类型一样了 而其他的引用类型不变哦

     如果我的基本类型以及String类型直接克隆了 没有做任何修改 看看会好玩不

    package YuanXingModel;
    
    public class Client {
    
        public static void main(String[] args) {
    
                Book book1 = new Book();
                book1.setTitle("算法导论");
                book1.addImg("图1");
                book1.addImg("图2");
                book1.setNum(300);
                book1.showBook();
                System.out.println("#############################");
            // 克隆一个 以原型方式进行复制
            try {
                Book book2 = (Book) book1.clone();
                book2.setTitle("设计模式");
                book2.addImg("图片A");
                book2.addImg("图片B");
                book2.setNum(900);
                book2.showBook();
                System.out.println(book1==book2);
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            book1.showBook();  //再看看以前的
            
        }
    }

    运行结果

    大家自己玩玩看看!挺好玩的 我自己在写博客时候 感觉自己做了个排列组合~~

     

    原型模式分为浅复制和深复制

    浅复制 —-只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。

    深复制 —-在计算机中开辟了一块新的内存地址用于存放复制的对象。

     

     

     

     

     

     

     

  • 相关阅读:
    BLOB
    cesium 检测视图改变的代码
    有关Nodejs的一些插件介绍
    线程基础知识
    进程和线程概念对比
    C#对象与XMl文件之间的相互转换(转)
    简介C#读取XML的方式(转)
    关于c# Debug和Release的区别 (转)
    c++堆和栈(转)
    浅谈C#堆栈与托管堆的工作方式(转)
  • 原文地址:https://www.cnblogs.com/toov5/p/9870984.html
Copyright © 2020-2023  润新知