1、背景

    1. public class Client {
    2. //发送邮件的数量
    3. private static int MAX_COUNT = 3;
    4. public static void main(String[] args) {
    5. int i = 0;
    6. //定义模板
    7. Mail mail = new Mail(new AdvTemplate());
    8. //模拟发送场景
    9. while (i < MAX_COUNT) {
    10. mail.setApplication(getRandomString(5) + " 先生(女士) ");
    11. mail.setReceiver(getRandomString(5) + "@" + getRandomString(8) + ".com");
    12. sendMail(mail);
    13. i++;
    14. }
    15. }
    16. //发送邮件
    17. public static void sendMail(Mail mail) {
    18. System.out.println("标题:" + mail.getSubject() + "\t收件人:" + mail.getReceiver() + "\t...发送成功!");
    19. }
    20. //获得指定长度的随机字符串
    21. public static String getRandomString(int maxLength) {
    22. String source = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    23. StringBuffer sb = new StringBuffer();
    24. Random random = new Random();
    25. for (int i = 0; i < maxLength; i++) {
    26. sb.append(source.charAt(random.nextInt(source.length())));
    27. }
    28. return sb.toString();
    29. }
    30. }

    看到实现结果,长舒了一口气,终于实现了。可是,仔细观察一下我们的设计,会发现存在很大的问题:程序是单线程的,批量发送耗时太长,假如每天要给600万用户发送邮件,按照一封0.02秒计算,需要33小时。。。

    2、Prototype的优点
    性能优良:原型模式是在内存中拷贝二进制流,要比直接new一个对象好得多,特别是在一个循环体内产生大量对 象时,原型模式能更好的体现其优点。
    逃避构造函数的约束:直接在内存中拷贝,不会执行构造函数,减少了约束

    Prototype的使用场景
    资源优化场景:类初始化需要消耗非常多的资源,所以在需要使用大量同一对象的时候可以考虑原型模式
    性能和安全要求的场景:通过new产生一个对象要非常繁琐的数据准备或访问权限,可以使用原型模式替代
    一个对象多个修改者场景:一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改该对象的值,可以 使用原型模式拷贝多个对象供调用者使用

    3、深浅拷贝的代码

    1. package com.aliyun.sales.lead.service.action.impl;
    2. class Address /*implements Cloneable*/{
    3. private String country;
    4. private String province;
    5. private String city;
    6. public String getCountry() {
    7. return country;
    8. }
    9. public void setCountry(String country) {
    10. this.country = country;
    11. }
    12. public String getProvince() {
    13. return province;
    14. }
    15. public void setProvince(String province) {
    16. this.province = province;
    17. }
    18. public String getCity() {
    19. return city;
    20. }
    21. public void setCity(String city) {
    22. this.city = city;
    23. }
    24. @Override
    25. public String toString() {
    26. return "Address [country=" + country + ", province=" + province
    27. + ", city=" + city + "]";
    28. }
    29. public Address(String country, String province, String city) {
    30. super();
    31. this.country = country;
    32. this.province = province;
    33. this.city = city;
    34. }
    35. /* @Override
    36. public Address clone() throws CloneNotSupportedException {
    37. return (Address) super.clone();
    38. }*/
    39. }
    1. package com.aliyun.sales.lead.service.action.impl;
    2. class Customer implements Cloneable{
    3. public int ID;
    4. public int age;
    5. public Address address;
    6. public int getID() {
    7. return ID;
    8. }
    9. public void setID(int iD) {
    10. ID = iD;
    11. }
    12. public int getAge() {
    13. return age;
    14. }
    15. public void setAge(int age) {
    16. this.age = age;
    17. }
    18. public Address getAddress() {
    19. return address;
    20. }
    21. public void setAddress(Address address) {
    22. this.address = address;
    23. }
    24. public Customer(int iD, int age, Address address) {
    25. super();
    26. ID = iD;
    27. this.age = age;
    28. this.address = address;
    29. }
    30. @Override
    31. public String toString() {
    32. return "Customer [ID=" + ID + ", age=" + age + ", address=" + address
    33. + "]";
    34. }
    35. @Override
    36. public Customer clone() throws CloneNotSupportedException {
    37. Customer customer = (Customer) super.clone();
    38. /*customer.address = address.clone();*/
    39. return customer;
    40. }
    41. public static void main(String[] args) throws CloneNotSupportedException {
    42. Address address = new Address("CH" , "SD" , "QD");
    43. Customer customer1 = new Customer(1 , 23 , address);
    44. Customer customer2 = customer1.clone();
    45. customer2.getAddress().setCity("JN");
    46. customer2.setID(2);
    47. System.out.println("customer1:"+customer1.toString());
    48. System.out.println("customer2:"+customer2.toString());
    49. }
    50. }

    实现一个Clonable接口,就是一个需要标识;
    重写Object的clone方法;

    4、深浅拷贝的区别
    深浅拷贝都是针对引用类型的属性来说的,应为基本类型的名和值都存放在栈中,clone的时候名和值都克隆一份到栈中,如果是引用类型,引用类型属性的值存放在堆中,名字存放到栈中,但是在栈中存放了堆中值的地址,浅拷贝就是在栈中拷贝一份名字和堆中值得地址,而深拷贝是将堆中值得在堆中开辟一块内存拷贝一份新的,栈中的名称对应值的引用是新开辟的那块内存的地址。
    参考https://blog.csdn.net/weixin_41910848/article/details/82144671