• 设计模式---原型模式


    定义:
    指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
    不需要知道任何创建细节,不调用构造函数
    适用场景:
    类初始化消耗较多的资源
    new产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
    构造函数比较复杂
    循环体中生产大量对象时
    优点:
    原型模式性能比直接new一个对象的性能高
    可以简化创建过程
    缺点:
    必须配备克隆方法
    对克隆复杂对象或对克隆出的对象进行复杂改造时,容易引入风险
    深拷贝、浅拷贝要运用得当
    扩展:
    深克隆
    浅克隆

    Coding

    public class Mail implements Cloneable{
    
        private String name;
        private String emailAddress;
        private String content;
    
        public Mail() {
            System.out.println("Mail Class Construct invoke");
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getEmailAddress() {
            return emailAddress;
        }
    
        public void setEmailAddress(String emailAddress) {
            this.emailAddress = emailAddress;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    
        @Override
        public String toString() {
            return "Mail{" +
                    "name='" + name + '\'' +
                    ", emailAddress='" + emailAddress + '\'' +
                    ", content='" + content + '\'' +
                    '}';
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            System.out.println("clone mail object");
            return super.clone();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    public class Test {
    
        public static void main(String[] args) throws CloneNotSupportedException {
            Mail mail = new Mail();
            mail.setContent("初始化模板");
            for (int i = 0; i < 10; i++) {
                Mail mailTemp = (Mail)mail.clone();
                mailTemp.setName("姓名:" + i);
                mailTemp.setContent("恭喜您,此次活动中奖");
                mailTemp.setEmailAddress("姓名" + i + "@imooc.com");
                MailUtil.sendMail(mailTemp);
            }
            MailUtil.saveOriginMailRecord(mail);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    //new Mail时打印 进入了构造器方法中,之后的clone对象 都没有进行构造器的调用,都是基于二进制流进行的复制
    Mail Class Construct invoke
    clone mail object
    向姓名:0同学,邮件地址:姓名0@imooc.com,邮件内容:恭喜您,此次活动中奖发送邮件成功
    clone mail object
    向姓名:1同学,邮件地址:姓名1@imooc.com,邮件内容:恭喜您,此次活动中奖发送邮件成功
    clone mail object
    向姓名:2同学,邮件地址:姓名2@imooc.com,邮件内容:恭喜您,此次活动中奖发送邮件成功
    clone mail object
    向姓名:3同学,邮件地址:姓名3@imooc.com,邮件内容:恭喜您,此次活动中奖发送邮件成功
    clone mail object
    向姓名:4同学,邮件地址:姓名4@imooc.com,邮件内容:恭喜您,此次活动中奖发送邮件成功
    clone mail object
    向姓名:5同学,邮件地址:姓名5@imooc.com,邮件内容:恭喜您,此次活动中奖发送邮件成功
    clone mail object
    向姓名:6同学,邮件地址:姓名6@imooc.com,邮件内容:恭喜您,此次活动中奖发送邮件成功
    clone mail object
    向姓名:7同学,邮件地址:姓名7@imooc.com,邮件内容:恭喜您,此次活动中奖发送邮件成功
    clone mail object
    向姓名:8同学,邮件地址:姓名8@imooc.com,邮件内容:恭喜您,此次活动中奖发送邮件成功
    clone mail object
    向姓名:9同学,邮件地址:姓名9@imooc.com,邮件内容:恭喜您,此次活动中奖发送邮件成功
    存储OriginMail记录,OriginMail:初始化模板
    
    Process finished with exit code 0
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    浅克隆演示:

    import java.util.Date;
    
    public class Pig implements Cloneable {
    
        private String name;
    
        private Date birthday;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        @Override
        public String toString() {
            return "Pig{" +
                    "name='" + name + '\'' +
                    ", birthday=" + birthday +
                    '}';
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
        public static void main(String[] args) throws CloneNotSupportedException {
            Pig pig = new Pig();
            pig.setName("佩奇");
            pig.setBirthday(new Date());
            Pig pig2 = (Pig)pig.clone();
            System.out.println(pig == pig2);
            System.out.println(pig.getBirthday() == pig2.getBirthday());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    //pig 与 pig2是不同的两个对象
    false
    //pig的birthday 与 pig2的birthday是一个对象引用
    true
    
    • 1
    • 2
    • 3
    • 4

    修复:

    import java.util.Date;
    
    public class Pig implements Cloneable {
    
        private String name;
    
        private Date birthday;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        @Override
        public String toString() {
            return "Pig{" +
                    "name='" + name + '\'' +
                    ", birthday=" + birthday +
                    '}';
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            Pig pig = (Pig)super.clone();
            //对birthday单独进行clone
            pig.birthday = (Date)pig.birthday.clone();
            return pig;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    防止调用clone方法来破坏单例模式:
    1、不去实现Cloneable接口
    2、重写clone的方法实现

    import java.io.Serializable;
    
    public class HungrySingleton implements Serializable,Cloneable {
    
        private final static HungrySingleton hungrySingleton;
    
        static {
            hungrySingleton = new HungrySingleton();
        }
    
        private HungrySingleton() {
            //防止反射调用
            if (hungrySingleton != null) {
                throw new RuntimeException("单例构造器禁止反射调用");
            }
        }
    
        public static HungrySingleton getInstance() {
            return hungrySingleton;
        }
    
        //防止反序列化
        public Object readResolve() {
            return hungrySingleton;
        }
    
    	//重写clone的方法实现
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return hungrySingleton;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    ArrayList、HashMap等都有采用原型模式

  • 相关阅读:
    java开发手册-06工程结构
    Eclipse配置tomcat
    数据结构第5章课后习题答案
    新疆维吾尔自治区工程系列建筑专业职称评审条件
    python(27)反射机制
    java计算机毕业设计中小企业的在线工作日志管理系统源程序+mysql+系统+lw文档+远程调试
    Java(100):Java操作ES增删查(RestHighLevelClient)
    安装Redis
    RocketMq消息持久化(一)——存储架构设计概述
    深入理解ThreadLocal
  • 原文地址:https://blog.csdn.net/qq_36364521/article/details/125872451