zoukankan      html  css  js  c++  java
  • 原型模式

    什么是原型模式

    克隆

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

    原型模式应用场景

    (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();  //再看看以前的
            
        }
    }

    运行结果

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

     

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

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

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

     

     

     

     

     

     

     

  • 相关阅读:
    一张图片入门Python
    4.1. 如何在Windows环境下开发Python
    你必须知道的EF知识和经验
    XUnit的使用
    如何使用NUnit
    Entity Framework 不支持DefaultValue
    Have You Ever Wondered About the Difference Between NOT NULL and DEFAULT?
    Validation failed for one or more entities. See 'EntityValidationErrors' property for more details
    Entity Framework 与多线程
    sqlite中的自增主键
  • 原文地址:https://www.cnblogs.com/toov5/p/9870984.html
Copyright © 2011-2022 走看看