精华内容
下载资源
问答
  • 原型模式类图

    2017-11-14 21:13:00
    用Viso画的UML。 转载于:https://www.cnblogs.com/longdb/p/7834690.html

    用Viso画的UML。

     

    转载于:https://www.cnblogs.com/longdb/p/7834690.html

    展开全文
  • 原型模式

    千次阅读 2018-06-12 09:47:26
    原型模式是简单程度仅次于单例模式的简单模式,它的定义可以简单理解为对象的拷贝,通过拷贝的方式创建一个已有对象的新对象,这就是原型模式。 设计类图:   在原型模式中主要的任务是实现一个接口,这个接口...

    定义:

    给出一个原型对象实例来指定创建对象的类型,并通过拷贝这些原型的方式来创建新的对象。

    原型模式是简单程度仅次于单例模式的简单模式,它的定义可以简单理解为对象的拷贝,通过拷贝的方式创建一个已有对象的新对象,这就是原型模式。

    设计类图:

      在原型模式中主要的任务是实现一个接口,这个接口具有一个clone方法可以实现拷贝对象的功能,也就是上图中的ProtoType接口。由于在Java语言中,JDK已经默认给我们提供了一个Coneable接口,所以我们不需要手动去创建ProtoType接口类了。Coneable接口在java中是一个标记接口,它并没有任何方法,只有实现了Coneable接口的类在JVM当中才有可能被拷贝。既然Coneable接口没有任何方法,那clone方法从哪里来呢?由于在java中所有的类都是Object类的子类,所以我们只需要重写来自Object类的clone方法就可以了。
    示例代码如下:

    public class ProtoTypeClass implements Cloneable {
    
        @Override
        protected ProtoTypeClass clone() throws CloneNotSupportedException {
            return (ProtoTypeClass)super.clone();
        }
    }
    
    public class Client {
    
        public static void main(String[] args) {
            ProtoTypeClass protoType = new ProtoTypeClass();
    
            try {
                //通过clone生成一个ProtoTypeClass类型的新对象
                ProtoTypeClass cloneObject = protoType.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
        }
    }

      看吧,原型模式的代码简直不要太简单,简单到不能再简单了,只需要实现Cloneable接口,然后覆写clone方法,调用super.clone就可以实现简单的对象复制了。
      值得注意的是,使用clone方法创建的新对象的构造函数是不会被执行的,也就是说会绕过任何构造函数(有参和无参),因为clone方法的原理是从堆内存中以二进制流的方式进行拷贝,直接分配一块新内存。

    深拷贝和浅拷贝

    浅拷贝

    浅拷贝只会拷贝对象本身相关的基本类型数据,直接看示例代码:

    public class EasyCopyExample implements Cloneable {
        private List<String> nameList = new ArrayList<>();
    
        @Override
        protected EasyCopyExample clone() throws CloneNotSupportedException {
            return (EasyCopyExample) super.clone();
        }
    
        public void addName(String name) {
            nameList.add(name);
        }
    
        public void printNames() {
            for (String name : nameList) {
                System.out.println(name);
            }
        }
    }
    public class Client {
        public static void main(String[] args) {
            try {
                //创建一个原始对象并添加一个名字
                EasyCopyExample originalObject = new EasyCopyExample();
                originalObject.addName("test1");
    
                //克隆一个新对象并添加一个名字
                EasyCopyExample cloneObject = originalObject.clone();
                cloneObject.addName("test2");
    
                //打印原始对象和新对象的name
                originalObject.printNames();
                System.out.println();
                cloneObject.printNames();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
    
        }
    }

    输出结果:
    这里写图片描述
      可以看到通过clone()创建的新对象与之前的对象都打印出了相同的name, 这说明新对象与原始对象是共用nameList的这个成员变量的,这就是浅拷贝,拷贝之后的对象会和原始对象共用一部分数据,这样会给使用上带来困扰,因为一个变量不是静态的但却可以多个对象同时修改它的值。在java中除了基本数据类型(int long等)和String类型,数组引用和对象引用的成员变量都不会被拷贝。

    深拷贝

    为了避免上面的情况,我们就需要对具有clone方法不支持拷贝的数据的对象自行处理,将上述示例代码修改如下:

    public class DeepCopyExample implements Serializable {
        private List<String> nameList = new ArrayList<>();
        private String name = "张三";
        private int age = 23;
    
        public DeepCopyExample deepClone() throws IOException, ClassNotFoundException {
            //将对象写到流里
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            //从流里读回来
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (DeepCopyExample) ois.readObject();
        }
    
        public void addName(String name) {
            nameList.add(name);
        }
    
        public void printNames() {
            for (String name : nameList) {
                System.out.println(name);
            }
            System.out.println(name);
            System.out.println(age);
        }
    }
    public class Client {
        public static void main(String[] args) {
            try {
                //创建一个原始对象并添加一个名字
                DeepCopyExample originalObject = new DeepCopyExample();
                originalObject.addName("test1");
    
                //克隆一个新对象并添加一个名字
                DeepCopyExample cloneObject = originalObject.deepClone();
                cloneObject.addName("test2");
    
                //打印原始对象和新对象的name
                originalObject.printNames();
                System.out.println("-----------");
                cloneObject.printNames();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    输出结果:
    这里写图片描述
      上面的代码是通过序列化和反序列化的方式实现对象的拷贝的,通过实现Serializable接口,对象可以写到一个流里(序列化),再从流里读回来(反序列化),便可以重建对象。可以看到输出结果中新对象保留了原始对象的基本类型数据(name和age),同时针对新对象操作List数据不会影响原始对象,这说明跟原始对象是完全隔离开了,是两个完全独立的对象。

      能够使用这种方式做的前提是,对象以及对象内部所有引用到的对象都是可序列化的,否则,就需要仔细考察那些不可序列化的对象可否设成transient,从而将之排除在复制过程之外。

      有一些对象,比如线程(Thread)对象或Socket对象,是不能简单复制或共享的。不管是使用浅度克隆还是深度克隆,只要涉及这样的间接对象,就必须把间接对象设成transient而不予复制;或者由程序自行创建出相当的同种对象。

    原型模式的优缺点

      优点很明显就是可以绕过繁琐的构造函数,快速创建对象,且比直接new一个对象性能优良,因为是直接内存二进制流拷贝。原型模式非常适合于你想要向客户隐藏实例创建的创建过程的场景,提供客户创建未知类型对象的选择。

      原型模式最主要的缺点是每一个类都必须配备一个克隆方法。配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类来说不是很难,而对于已经有的类不一定很容易,特别是当一个类引用不支持序列化的间接对象,或者引用含有循环结构的时候。



    参考:

    展开全文
  • 转载:https://blog.csdn.net/chenliguan/article/details/698557381 原型模式概念1.1 介绍 原型模式是一个创建型的模式。原型二字表明了改模式应该有一个样板实例,用户从这个样板对象中复制一个内部属性一致的...

    转载:https://blog.csdn.net/chenliguan/article/details/69855738

    1 原型模式概念

    1.1 介绍

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

    1.2 定义

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

    1.3 使用场景

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

    2 原型模式UML类图(通用)

    这里写图片描述

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

    2 简单实现示范

    2.1 原型

    /*
     * 书本类型,扮演的是ConcretePrototype角色,而Cloneable扮演Prototype角色
     */
    public class Book implements Cloneable {
    
        private String title;// 标题
        private ArrayList<String> image = new ArrayList<String>();// 图片名列表
    
        public Book() {
            super();
        }
    
        /**
         * 重写拷贝方法
         */
        @Override
        protected Book clone()  {
            try {
                Book book = (Book) super.clone();
                return book;
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public ArrayList<String> getImage() {
            return image;
        }
    
        public void addImage(String img) {
            this.image.add(img);
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        /**
         * 打印内容
         */
        public void showBook() {
            System.out.println("----------------------Start----------------------");
    
            System.out.println("title:" + title);
            for (String img : image) {
                System.out.println("image name:" + img);
            }
    
            System.out.println("----------------------End----------------------");
        }
    }

    2.2 Client端1

    (1)代码

    
    public class Client {
    
        public static void main(String[] args) {
            // 1.构建书本对象
            Book book1 = new Book();        
            // 2.编辑书本,添加图片
            book1.setTitle("书1");
            book1.addImage("图1");
            book1.showBook();
    
            // 以原型文档为原型,拷贝一份副本
            Book book2 = (Book) book1.clone();
            book2.showBook();
            // 修改图书副本,不会影响原始书本
            book2.setTitle("书2");
            book2.showBook();
    
            // 再次打印原始书本
            book1.showBook();
        }
    }

    (2)结果:

    ----------------------Start----------------------
    title:书1
    image name:图1
    ----------------------End----------------------
    ----------------------Start----------------------
    title:书1
    image name:图1
    ----------------------End----------------------
    ----------------------Start----------------------
    title:书2
    image name:图1
    ----------------------End----------------------
    ----------------------Start----------------------
    title:书1
    image name:图1
    ----------------------End----------------------

    (3)解释: 
      book2是book的一份拷贝,它和book1的内容是一样的。而book2修改了“标题”-字符串(基本的数据类型),并不影响book1的标题,这就保证了book1的安全性。

    2.3 浅拷贝应用

    (1)代码:

    public class Client {
    
        public static void main(String[] args) {
            // 1.构建书本对象
            Book book1 = new Book();        
            // 2.编辑书本,添加图片
            book1.setTitle("书1");
            book1.addImage("图1");
            book1.showBook();
    
            // 以原型文档为原型,拷贝一份副本
            Book book2 = (Book) book1.clone();
            book2.showBook();
            // 修改图书副本,不会影响原始书本
            book2.setTitle("书2");
            book2.addImage("图2");
            book2.showBook();
    
            // 再次打印原始书本
            book1.showBook();
        }
    }

    (2)结果:

    ----------------------Start----------------------
    title:书1
    image name:图1
    ----------------------End----------------------
    ----------------------Start----------------------
    title:书1
    image name:图1
    ----------------------End----------------------
    ----------------------Start----------------------
    title:书2
    image name:图1
    image name:图2
    ----------------------End----------------------
    ----------------------Start----------------------
    title:书1
    image name:图1
    image name:图2
    ----------------------End----------------------

    (3)解释: 
      细心观察发现,最后两个书本内容输出是一致的。引用类型的新对象book2的image只是单纯指向了this.image引用,并没有重新构造一个image对象,然后将原始书本的图片添加到新的image对象中,这样导致book2中的image与原始书本中的是同一个对象。因此,修改其中一个书本的图片,另一个书本也会受到影响。 
      如何解决?因为Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、集合、容器对象、引用对象等都不会拷贝;所以采用深拷贝。

    2.3 深拷贝应用

    (1)代码:

    /**
         * 重写拷贝方法
         */
        @Override
        protected Book clone()  {
            try {
                Book book = (Book) super.clone();
                // 对image对象也调用clone()函数,进行拷贝
                book.image = (ArrayList<String>) this.image.clone();
                return book;
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return null;
        }

    (2)结果:

    ----------------------Start----------------------
    title:书1
    image name:图1
    ----------------------End----------------------
    ----------------------Start----------------------
    title:书1
    image name:图1
    ----------------------End----------------------
    ----------------------Start----------------------
    title:书2
    image name:图1
    image name:图2
    ----------------------End----------------------
    ----------------------Start----------------------
    title:书1
    image name:图1
    ----------------------End----------------------

    (3)解释:

    将book.image指向this.image的一份拷贝,而不是this.image本身,实现了完全的拷贝,这样再互不影响。

    3 Android源码中的原型模式

    3.1 Intent

    Uri uri = Uri.parse("smsto:110");
            Intent intent = new Intent(Intent.ACTION_SEND,uri);
            intent.putExtra("sms_body", "The SMS text");
            //克隆
            Intent intent2 = (Intent)intent.clone();
            startActivity(intent2);

    4 总结

    4.1 优点

    (1)原型模式是在内存中二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量对象时,原型模式可能更好的体现其优点。 
    (2)还有一个重要的用途就是保护性拷贝,也就是对某个对象对外可能是只读的,为了防止外部对这个只读对象的修改,通常可以通过返回一个对象拷贝的形式实现只读的限制。

    4.2 缺点

    (1)这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的,在实际开发中应该注意这个潜在问题。优点是减少了约束,缺点也是减少了约束,需要大家在实际应用时考虑。 
    (2)通过实现Cloneable接口的原型模式在调用clone函数构造实例时并不一定比通过new操作速度快,只有当通过new构造对象较为耗时或者说成本较高时,通过clone方法才能够获得效率上的提升。

    5 注意事项

    5.1 构造函数不会被执行

      一个实现了Cloneable并重写了clone方法的类A,有一个无参构造或有参构造B,通过new关键字产生了一个对象S,再然后通过S.clone()方式产生了一个新的对象T,那么在对象拷贝时构造函数B是不会被执行的。我们来写一小段程序来说明这个问题。

    public class Thing implements Cloneable {
    
        public Thing(){ 
            System.out.println("构造函数被执行了...");
        }
    
        @Override
        public Thing clone(){ 
            Thing thing=null; 
            try {
                thing = (Thing)super.clone();
            } catch (CloneNotSupportedException e) { 
                e.printStackTrace();
            }
            return thing;
        }
    }

      然后我们再来写一个Client类,进行对象的拷贝:

    public class Client {
    
        public static void main(String[] args) { 
            Thing thing = new Thing(); //产生一个对象
            Thing cloneThing = thing.clone(); //拷贝一个对象
        }
    }

      运行结果如下所示:

    构造函数被执行了...
    • 1

      对象拷贝时构造函数确实没有被执行,这点从原理来讲也是可以讲得通的,Object类的clone方法的原理是从内存中(具体地说就是堆内存)以二进制流的方式进行拷贝,重新分配一个内存块,那构造函数没有被执行是对的。

    5.2 浅拷贝和深拷贝

      在开发中,为减少错误,建议在使用原型模式时尽量使用深拷贝,避免操作副本时影响原始对象的问题。如果是在涉及类的继承时,父类有多个引用的情况就非常复杂,建议的方案是深拷贝和浅拷贝分开实现。

    5.3 clone与final两个冤家

      要使用clone方法,类的成员变量上不要增加final关键字。因为final类型是不允许重赋值的。

    6 原型模式实战

      以下代码是用户在登录之后通过LoginSession的setLoginedUser函数将登录用的信息设置在Session中,setLoginedUser是私有的,外部模块无法调用。

    (1)Address.java

    /**
     * @author Guan
     * 用户地址类
     */
    public class Address {
        public String city;
        public String district;
        public String street;
    
        public Address(String city, String district, String street) {
            this.city = city;
            this.district = district;
            this.street = street;
        }
    
        @Override
        public String toString() {
            return "Address{" +
                    "city='" + city + '\'' +
                    ", district='" + district + '\'' +
                    ", street='" + street + '\'' +
                    '}';
        }
    }

    (2)User.java

    /**
     * @author Guan
     * 用户实体类
     */
    public class User {
        public int age;
        public String name;
        public String phoneNum;
        public Address address;
    
        @Override
        public String toString() {
            return "User{" +
                    "age=" + age +
                    ", name='" + name + '\'' +
                    ", phoneNum='" + phoneNum + '\'' +
                    ", address=" + address +
                    '}';
        }
    }

    (3)LoginSession.java

    /**
     * @author Guan
     * 登录Session
     */
    public class LoginSession {
        static LoginSession loginSession = null;
        private User loginedUser;// 已登录用户
    
        public LoginSession() {
        }
    
        public static LoginSession getLoginSession() {
            if (loginSession == null) {
                loginSession = new LoginSession();
            }
            return loginSession;
        }
    
        public User getLoginedUser() {
    //        return loginedUser.clone();// 返回已登录用户的一个拷贝
            return loginedUser;// 返回原始已登录用户
        }
    
        // 只通过私有方法修改用户信息
        void setLoginedUser(User loginedUser) {
            this.loginedUser = loginedUser;
        }
    }

    (4)Login.java

    /**
     * @author Guan
     * 登录接口
     */
    public interface Login {
        void login();
    }

    (5)LoginImpl.java

    /**
     * @author Guan
     * 登录实现类
     */
    public class LoginImpl implements Login{
    
        public void login() {
            // 登录到服务器,获取到用户信息
            User loginedUser = new User();
    
            // 将服务器返回的完整信息设置给loginedUser对象
            loginedUser.age = 22;
            loginedUser.name = "xiaoguan";
            loginedUser.address = new Address("深圳市","宝安区","一路");
    
            // 登录完后将用户信息设置到Session中LoginSession.getLoginSession()中
            LoginSession.getLoginSession().setLoginedUser(loginedUser);
        }
    }

    (6)Client.java

    
    public class Client {
    
        public static void main(String[] args) {
    
            // 已登录用户
            LoginImpl loginImpl = new LoginImpl();
            loginImpl.login();
            User tempUser = LoginSession.getLoginSession().getLoginedUser();
    
            User user = LoginSession.getLoginSession().getLoginedUser();// 获得已登录的User对象
            user.address = new Address("新深圳市","新宝安区","新一路");
            // 只能通过私有方法setLoginedUser更新用户信息
            LoginSession.getLoginSession().setLoginedUser(user);
    
            System.out.println("tempUser:" + tempUser);
            System.out.println("已登录用户:" + LoginSession.getLoginSession().getLoginedUser());
        }
    }

    (7)结果&分析

      在用户点击更新按钮时候,直接调用以上代码更新用户地址,在网络请求成功还是未成功情况下用户信息都被修改了,结果打印如下:

    这里写图片描述 
      

    (8)优化

      所以需要使用原型模式来进行保护性拷贝,使得在任何地方调用getLoginedUser函数获取到的用户对象都是一个拷贝对象,即使客户端不小心修改了这个拷贝对象,也不会影响最初的已登录用户对象,确保了它的安全。修改代码如下:

    /**
     * @author Guan
     * 用户实体类
     */
    public class User implements Cloneable{
    
    
        /**
         * 拷贝
         */
        public User clone() {
            User user = null;
            try {
                user = (User) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return user;
        }
    
    
    }
    /**
     * @author Guan
     * 登录Session
     */
    public class LoginSession {
    
        public User getLoginedUser() {
            return loginedUser.clone();// 返回已登录用户的一个拷贝
    //      return loginedUser;// 返回原始已登录用户
        }
    
    }

      结果如下:

    这里写图片描述

    7 参考文章与链接

    《Android源码设计模式解析与实战》

    《设计模式之禅》

    《Android源码设计模式解析与实战》读书笔记(四)

    《 java 原型模式》

    展开全文
  • 原型模式(实例)

    千次阅读 2020-05-15 23:06:24
    目录原型模式1、模式结构2、模式实例2.1 应用场景类图2.2 代码实现3、模式分析3.1 优点3.2 缺点3.3 适用场景 原型模式   原型模式是一种对象创建型模式,建造者模式是一种对象创建型模式,用原型模式可以用原型...

    原型模式

      原型模式是一种对象创建型模式,建造者模式是一种对象创建型模式,用原型模式可以用原型实例指定创建对象的种类,它允许通过一个原型对象创建多个同类型的其他对象,而无需知道该对象的创建细节,在Java中可以直接使用Object提供的clone()方法来实现对象的克隆(浅克隆)。

    1、模式结构

    在这里插入图片描述
      Prototype:抽象原型类,给出所有的具体原型类所需的接口。
      ConcretePrototype:具体原型类,被复制的对象,此角色需要实现抽象的原型角色所要求的接口。
      Client:客户类。

    2、模式实例

      当汽车生产商批量生产汽车时,可以对于一个汽车型号进行批量生产,原型模式实现该机制,浅克隆时需要对汽车品牌做调整时,无需修改原车型,修改克隆得到的对象即可,深克隆时批量生产汽车时,汽车品牌也批量生产。

    2.1 应用场景类图

      原型模式浅克隆的应用类图如下:
      原型模式深克隆的应用类图如下:
    在这里插入图片描述

    2.2 代码实现

    浅克隆:
    (1)Brand.java

    public class Brand {
    	public void install(){
    		System.out.println("安装汽车品牌");
    	}
    }
    

    (2)Car.java

    public class Car implements Cloneable{
    	private Brand brand;
    	
    	public Car(){
    		this.brand = new Brand();
    	}
    	
    	@Override
    	protected Object clone() {
    		Car clone = null;
    		try {
    			clone = (Car)super.clone();
    		} catch (CloneNotSupportedException e) {
    			System.out.println("克隆失败...");
    		}
    		return clone;
    	}
    	
    	public Brand getBrand(){
    		return this.brand;
    	}
    	
    	public void run(){
    		System.out.println("小汽车能跑了");
    	}
    }
    

    (3)Client.java

    public class Client {
    	public static void main(String[] args) {
    		Car car,cloneCar;
    		car = new Car();
    		cloneCar = (Car)car.clone();
    		
    		System.out.println("car == cloneCar?");
    		System.out.println(car == cloneCar);
    		
    		System.out.println("car.getBrand() == cloneCar.getBrand()?");
    		System.out.println(car.getBrand() == cloneCar.getBrand());
    		
    		
    	}
    }
    

    深克隆:
    (1)Brand.java

    public class Brand implements Serializable{
    	private static final long serialVersionUID = 1L;
    
    	public void install(){
    		System.out.println("安装汽车品牌");
    	}
    }
    

    (2)Car.java

    public class Car implements Serializable{
    	private static final long serialVersionUID = 1L;
    	private Brand brand = null;
    	
    	public Car(){
    		this.brand = new Brand();
    	}
    	
    	public Object deepClone() throws IOException, ClassNotFoundException{
    		//将对象写入流中
    		ByteArrayOutputStream bao=new ByteArrayOutputStream();
    		ObjectOutputStream oos=new ObjectOutputStream(bao);
    		oos.writeObject(this);
    				
    		//将对象从流中取出
    		ByteArrayInputStream bis=new ByteArrayInputStream(bao.toByteArray());
    		ObjectInputStream ois=new ObjectInputStream(bis);
    		return(ois.readObject());
    	}
    	public Brand getBrand(){
    		return this.brand;
    	}
    	public void run(){
    		System.out.println("小汽车能跑了");
    	}
    }
    

    (3)Client.java

    public class Client {
    	public static void main(String[] args) {
    		Car car,cloneCar=null;
    		car = new Car();
    		try {
    			cloneCar = (Car) car.deepClone();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    		System.out.println("car == cloneCar?");
    		System.out.println(car == cloneCar);
    		
    		System.out.println("car.getBrand() == cloneCar.getBrand()?");
    		System.out.println(car.getBrand() == cloneCar.getBrand());
    	}
    }
    

    3、模式分析

      原型模式,在java中使用浅克隆时,当原型对象被复制时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制;而使用深克隆时,除了对象本身被复制外,对象所包含的所有成员变量也将被复制。

    3.1 优点

      原型模式简化了创建对象的过程,通过一个已有的实例进行复制提高了创建实例的效率,具有较好的可扩展性。

    3.2 缺点

      部分时候实现克隆可能较为麻烦。

    3.3 适用场景

      原型模式适合于当一个类初始化需要消耗很多资源时,有很多相似对象时,可以设计一个原型,通过对成员变量的些微修改来实现;需要时可以用深克隆的方式保存对象的状态,比如实现撤销操作等。

    参考文献:设计模式(第2版).清华出版社

    展开全文
  • 设计模型之原型模式(含UML完整实例)

    千次阅读 2020-04-08 19:24:19
    设计模型之原型模式 1.原型模式 1.1 定义   原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类...
  • 设计模式之原型模式

    千次阅读 2017-04-09 17:49:38
    1 原型模式概念1.1 介绍 原型模式是一个创建型的模式。原型二字表明了改模式应该有一个样板实例,用户从这个样板对象中复制一个内部属性一致的对象,这个过程也就是我们称的“克隆”。被复制的实例就是我们所称的...
  • 原型模式定义 定义 原型模式属于对象的创建型模式,通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象,这就是原型模式的用意
  • 23种设计模式(5):原型模式

    万次阅读 多人点赞 2012-03-26 08:58:25
    原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。Prototype类需要具备以下两个条件: 实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以...
  • 原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 原型模式其实就是从一个对象在创建另外一个可定制的对象,而且不需知道任何创建的细节 本样例代码(clone方法)仅...
  • 原型模式 原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式是实现了一个原型接口,该接口用于创建当前对象...
  • 原型模式  原型模式通过对既有对象的克隆来创建新的对象。 应用场景  在实际的开发过程中,原型模式的应用场景不多。最常用的是当实例化一个类需要大量的操作,例如数据库读取耗时较长时,通过存储一个对象,在...
  • 原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。Prototype类需要具备以下两个条件: 实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以...
  • 原型模式代码详解

    2020-11-30 15:47:34
    文章目录克隆羊问题传统方式解决克隆羊问题传统的方式的优缺点原型模式-基本介绍原型模式原理结构图-uml 类图原型模式解决克隆羊问题的应用实例原型模式在 Spring 框架中源码分析深入讨论-浅拷贝和深拷贝浅拷贝的...
  • 图解设计模式:23设计模式类图整理

    千次阅读 2019-05-11 19:21:10
    最近把《图解设计模式》又翻了一遍,为了方便记忆,将里面的类图和一些要点整理了一下。 设计模式在Gof中的分类: 创建型 Abstract Factory(抽象工厂)... Prototype(原型模式) 结构型 Ada...
  • 设计模式(十六)原型模式

    千次阅读 2017-06-26 00:11:53
    公众号有同学留言设计模式,才发现好久没有写设计模式了。关于创建型设计模式只差原型模式没写了,这一篇就来填补这个空缺。
  • PHP设计模式(六)-原型模式" date: 2016-06-07 10:22:51 +0800 comments: true categories: [php] 1、模式定义 通过创建原型使用克隆方法实现对象创建而不是使用标准的new 方式。 2、UML类图 image 3、...
  • 常见设计模式类图

    2021-05-23 15:17:18
    5、原型模式 二、结构型模式 1、适配器模式 2、桥接模式 3、组合模式 4、装饰者模式 5、外观模式 6、享元模式 7、代理模式 三、行为型模式 1、职责链模式 2、命令模式 3、解释器模式 4、迭代器模式 5...
  • java设计模式—原型模式(prototype pattern) 我们在程序开发过程中,都会遇到为一个类创建多个实例的情况,实例的创建开销很大,而且这些实例内部成员往往完全相同或仅有细微的差异,这种情况下如果能通过复制一个...
  • 在这里23种经典设计模式UML类图汇总

    千次阅读 多人点赞 2017-10-31 11:41:04
    创建型模式 1、FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的...
  • 设计模式对应类图汇总
  • uml建模 食堂售饭系统

    2012-02-01 16:51:23
    将所学过的涉及到建模的各种图联系在一起,主要涉及用例图,顺序图,合作图,活动图都有所体现
  • 原型模式包含如下角色: 抽象原型类:规定了具体原型对象必须实现的的 clone() 方法。 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。 访问类:使用具体原型类中的 clone() 方法来复制新的...
  • 23中设计模式类图和原理详解

    千次阅读 2016-09-14 08:42:55
    转载自:... 目录 创建型 1. Factory Method(工厂方法) 2. Abstract Factory(抽象工厂) 3. Builder(建造者) ...4. Prototype(原型) 5. Singleton(单例) 结构型 6. Ada
  • 原型模式介绍,包括应用场景,优缺点,模式结构,类图 以及 C++代码示例

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,269
精华内容 4,107
关键字:

原型模式的类图