一、单例设计模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

1,单例模式的结构

单例模式的主要有以下角色:
单例类。只能创建一个实例的类
访问类。使用单例类

2,单例模式的实现

单例设计模式分类两种:
饿汉式:类加载就会导致该单实例对象被创建
懒汉式:类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建

2.1,饿汉式

2.1.1,静态变量方式

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 12:08
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.hungry.staticVar
  5. * @ClassName: DataBase
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class DataBase {
  10. //私有构造方法
  11. private DataBase(){}
  12. //创建静态变量
  13. private static DataBase connection = new DataBase();
  14. //创建公共的静态获取变量方法
  15. public static DataBase getConnection(){
  16. return connection;
  17. }
  18. }
  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 12:12
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.hungry.staticVar
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) {
  11. DataBase var1 = DataBase.getConnection();//实例1
  12. DataBase var2 = DataBase.getConnection();//实例2
  13. System.out.println(var1.equals(var2));
  14. }
  15. }

2.1.2,静态代码块方式

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 12:15
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.hungry.staticBlock
  5. * @ClassName: DataBase
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class DataBase {
  10. private DataBase(){}
  11. private static DataBase connection ;
  12. static {
  13. connection = new DataBase();
  14. }
  15. public static DataBase getConnection(){
  16. return connection;
  17. }
  18. }
  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 12:12
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.hungry.staticVar
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) {
  11. DataBase var1 = DataBase.getConnection();
  12. DataBase var2 = DataBase.getConnection();
  13. System.out.println(var1.equals(var2));
  14. }
  15. }

2.2,懒汉式

2.2.1,线程不安全

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 12:23
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.lazy.safety
  5. * @ClassName: DataBase
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class DataBase {
  10. //1,将构造器私有化
  11. private DataBase(){}
  12. //2,声明私有化成员变量
  13. private static DataBase connection = null;
  14. //3,成员方法初始化成员变量
  15. public static DataBase getConnection(){
  16. //判空
  17. if (connection == null){
  18. connection = new DataBase();
  19. }
  20. return connection;
  21. }
  22. }
  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 12:28
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.lazy.safety
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) {
  11. DataBase conn1 = DataBase.getConnection();
  12. DataBase conn2 = DataBase.getConnection();
  13. System.out.println(conn1.equals(conn2));
  14. }
  15. }

2.2.2,线程安全(同步锁)

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 12:30
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.lazy.unSafety
  5. * @ClassName: DataBase
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class DataBase {
  10. private DataBase(){}
  11. private static DataBase connection ;
  12. public synchronized static DataBase getConnection(){
  13. if (connection == null){
  14. connection = new DataBase();
  15. }
  16. return connection;
  17. }
  18. }
  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 12:32
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.lazy.safety
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) {
  11. DataBase conn1 = DataBase.getConnection();
  12. DataBase conn2 = DataBase.getConnection();
  13. System.out.println(conn1.equals(conn2));
  14. }
  15. }

2.3,双检锁(volatile模式)

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 14:42
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.lazy.doubleLock
  5. * @ClassName: DataBase
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class DataBase {
  10. //private constructor
  11. private DataBase(){}
  12. //member variable ; volatile 保证关键字可以保证可见性和有序性
  13. private static volatile DataBase connection ;
  14. //public method
  15. public static DataBase getConnection(){
  16. //validate connection
  17. if (connection == null){
  18. //synchronized lock
  19. synchronized (DataBase.class){
  20. //validate again after getting the lock
  21. if (connection == null){
  22. connection = new DataBase();
  23. }
  24. }
  25. }
  26. return connection;
  27. }
  28. }
  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 14:48
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.lazy.doubleLock
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) {
  11. DataBase conn1 = DataBase.getConnection();
  12. DataBase conn2 = DataBase.getConnection();
  13. System.out.println(conn1.equals(conn2));
  14. }
  15. }

2.4,静态内部类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 14:53
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.lazy.static_inner_class
  5. * @ClassName: DataBase
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class DataBase {
  10. //private constructor
  11. private DataBase(){}
  12. //static inner class
  13. private static class DataBaseHolder{
  14. private static final DataBase CONNECTION = new DataBase();
  15. }
  16. /**
  17. * 静态内部类单例模式中实例由内部类创建,由于 JVM 在加载外部类的过程中, 是不会加载静态
  18. * 内部类的, 只有内部类的属性/方法被调用时才会被加载, 并初始化其静态属性。静态属性由于被
  19. * static 修饰,保证只被实例化一次,并且严格保证实例化顺序。
  20. *
  21. * 说明:
  22. * 第一次加载Singleton类时不会去初始化INSTANCE,只有第一次调用getInstance,虚拟机加
  23. * 载SingletonHolder
  24. * 并初始化INSTANCE,这样不仅能确保线程安全,也能保证 Singleton 类的唯一性。
  25. *
  26. */
  27. //public method
  28. public static DataBase getConnection(){
  29. return DataBaseHolder.CONNECTION;
  30. }
  31. }
  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 14:56
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.lazy.static_inner_class
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) {
  11. DataBase conn1 = DataBase.getConnection();
  12. DataBase conn2 = DataBase.getConnection();
  13. System.out.println(conn1.equals(conn2));
  14. }
  15. }

2.5,枚举方式

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 15:00
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.enum_
  5. * @ClassName: DataBase
  6. * @Description: 枚举方式实现
  7. * @Version 1.0
  8. */
  9. public enum DataBase {
  10. Connection;
  11. /**
  12. *枚举类实现单例模式是极力推荐的单例实现模式,因为枚举类型是线程安全的,并且只会装载一
  13. * 次,设计者充分的利用了枚举的这个特性来实现单例模式,枚举的写法非常简单,而且枚举类型是
  14. * 所用单例实现中唯一一种不会被破坏的单例实现模式。
  15. */
  16. }
  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 15:00
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.enum_
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) {
  11. DataBase conn1 = DataBase.Connection;
  12. DataBase conn2 = DataBase.Connection;
  13. System.out.println(conn1.equals(conn2));
  14. }
  15. }

3,存在的问题

上面定义的单例类(Singleton)可以创建多个对象,枚举方式除外。有两种方式,分别是序列化反射

3.1,序列化与反序列化

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 14:53
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.lazy.static_inner_class
  5. * @ClassName: DataBase
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class DataBase implements Serializable {
  10. //private constructor
  11. private DataBase(){}
  12. //static inner class
  13. private static class DataBaseHolder{
  14. private static final DataBase CONNECTION = new DataBase();
  15. }
  16. /**
  17. * 静态内部类单例模式中实例由内部类创建,由于 JVM 在加载外部类的过程中, 是不会加载静态
  18. * 内部类的, 只有内部类的属性/方法被调用时才会被加载, 并初始化其静态属性。静态属性由于被
  19. * static 修饰,保证只被实例化一次,并且严格保证实例化顺序。
  20. *
  21. * 说明:
  22. * 第一次加载Singleton类时不会去初始化INSTANCE,只有第一次调用getInstance,虚拟机加
  23. * 载SingletonHolder
  24. * 并初始化INSTANCE,这样不仅能确保线程安全,也能保证 Singleton 类的唯一性。
  25. *
  26. */
  27. //public method
  28. public static DataBase getConnection(){
  29. return DataBaseHolder.CONNECTION;
  30. }
  31. //解决序列化破坏单例的方案
  32. private Object readResolve(){
  33. return DataBaseHolder.CONNECTION;
  34. }
  35. }
  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 14:56
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.lazy.static_inner_class
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) {
  11. //writeObjectToFile();
  12. DataBase conn1 = readObjectFromFile();
  13. DataBase conn2 = readObjectFromFile();
  14. System.out.println(conn1.equals(conn2));
  15. }
  16. //读取对象,写入文件
  17. public static void writeObjectToFile(){
  18. try {
  19. //1,获取对象
  20. DataBase conn = DataBase.getConnection();
  21. //2,创建对象输出流
  22. ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("H:\\desktop\\a.txt"));
  23. //3,将对象写入文件中
  24. oos.writeObject(conn);
  25. } catch (IOException e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. //读取文件,转为对象
  30. public static DataBase readObjectFromFile(){
  31. DataBase conn = null;
  32. try {
  33. //1,获取文件
  34. ObjectInputStream ois = new ObjectInputStream(new FileInputStream("H:\\desktop\\a.txt"));
  35. //2,读取对象
  36. conn = (DataBase) ois.readObject();
  37. System.out.println(conn);
  38. } catch (Exception e) {
  39. e.printStackTrace();
  40. }finally {
  41. return conn;
  42. }
  43. }
  44. }

3.2,反射

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 14:42
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.lazy.doubleLock
  5. * @ClassName: DataBase
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class DataBase {
  10. //private constructor
  11. private DataBase(){
  12. if (connection != null){
  13. throw new RuntimeException();
  14. }
  15. }
  16. //member variable ; volatile 保证关键字可以保证可见性和有序性
  17. private static volatile DataBase connection ;
  18. //public method
  19. public static DataBase getConnection(){
  20. //validate connection
  21. if (connection != null){
  22. return connection;
  23. }
  24. //synchronized lock
  25. synchronized (DataBase.class){
  26. //validate again after getting the lock
  27. if (connection != null){
  28. return connection;
  29. }
  30. connection = new DataBase();
  31. return connection;
  32. }
  33. }
  34. }
  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 14:56
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.lazy.static_inner_class
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) {
  11. try {
  12. //1,获取DataBase的字节码对象
  13. Class<DataBase> clazz = DataBase.class;
  14. //2,获取无参构造方法
  15. Constructor<DataBase> constructor = clazz.getDeclaredConstructor();
  16. //3,取消访问权限
  17. constructor.setAccessible(true);
  18. //4,获取对象
  19. DataBase conn1 = constructor.newInstance();
  20. DataBase conn2 = constructor.newInstance();
  21. System.out.println(conn1.equals(conn2));
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }

4,Runtime源码解析

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/23 16:20
  4. * @PackageName:xyz.zhouge.designPatterns.singleton.RuntimeDemo
  5. * @ClassName: Test
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Test {
  10. public static void main(String[] args) {
  11. try {
  12. //获取Runtime类对象
  13. Runtime runtime = Runtime.getRuntime();
  14. //返回 Java 虚拟机中的内存总量。
  15. System.out.println(runtime.totalMemory());
  16. //返回 Java 虚拟机试图使用的最大内存量。
  17. System.out.println(runtime.maxMemory());
  18. //创建一个新的进程执行指定的字符串命令,返回进程对象
  19. Process process = runtime.exec("ipconfig");
  20. //获取命令执行后的结果,通过输入流获取
  21. InputStream inputStream = process.getInputStream();
  22. byte[] arr = new byte[1024 * 1024 * 100];
  23. int b = inputStream.read(arr);
  24. System.out.println(new String(arr, 0, b, "gbk"));
  25. } catch (Exception e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }

二、工厂模式

三、原型模式

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。

1,原型模式的结构

原型模式包含如下角色:
抽象原型类:规定了具体原型对象必须实现的的 clone() 方法。
具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
访问类:使用具体原型类中的 clone() 方法来复制新的对象。

2,原型模式的分类

原型模式的克隆分为浅克隆和深克隆。
浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。

3,浅克隆案例

3.1,案例一

image.png
image.png

3.1.1,克隆接口(抽象原型类)

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/28 12:44
  4. * @PackageName:xyz.zhouge.designPatterns.prototype.shallowCloning.abstractObject
  5. * @ClassName: Student
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public abstract class StudentPrototype implements Cloneable{
  10. }

3.1.2,具体原型类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/28 12:46
  4. * @PackageName:xyz.zhouge.designPatterns.prototype.shallowCloning.specificObject
  5. * @ClassName: Student
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Student extends StudentPrototype {
  10. public Student() {
  11. System.out.println("Student prototype object had created ...");
  12. }
  13. @Override
  14. public Student clone() throws CloneNotSupportedException {
  15. System.out.println("Student prototype object had cloned ...");
  16. return (Student) super.clone();
  17. }
  18. }

3.1.3,访问类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/29 14:24
  4. * @PackageName:xyz.zhouge.designPatterns.prototype.shallow_clone
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) throws CloneNotSupportedException {
  11. Student stu1 = new Student();
  12. Student stu2 = stu1.clone();
  13. System.out.println(stu1 == stu2);//false ,shallow clone
  14. /**
  15. *
  16. * 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
  17. *
  18. * 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
  19. */
  20. }
  21. }

3.2,案例二

image.png
image.png

3.2.1,克隆接口(抽象原型类)

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/29 14:32
  4. * @PackageName:xyz.zhouge.designPatterns.prototype.shallow_clone.demo2.abstractObject
  5. * @ClassName: CitationPrototype
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public abstract class CitationPrototype implements Cloneable{
  10. }

3.2.2,具体原型类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/29 14:33
  4. * @PackageName:xyz.zhouge.designPatterns.prototype.shallow_clone.demo2.specificObject
  5. * @ClassName: Citation
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Citation extends CitationPrototype {
  10. private String name ;
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. public Citation() {
  18. System.out.println("Citation object had created ...");
  19. }
  20. @Override
  21. public Citation clone() throws CloneNotSupportedException {
  22. System.out.println("Citation object had cloned ...");
  23. return (Citation) super.clone();
  24. }
  25. public void showCitation(){
  26. System.out.println(name + " 同学:在2021-2022学年第一学期中表现优秀,特发此状,以资鼓励!");
  27. }
  28. }

3.2.3,访问类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/29 14:37
  4. * @PackageName:xyz.zhouge.designPatterns.prototype.shallow_clone.demo2
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) throws CloneNotSupportedException {
  11. //test1();
  12. test2();
  13. }
  14. public static void test1() throws CloneNotSupportedException {
  15. //1,create prototype object
  16. Citation c1 = new Citation();
  17. c1.setName("zhangSan");
  18. //2,clone prototype object
  19. Citation c2 = c1.clone();
  20. c2.setName("lisi");
  21. c1.showCitation();
  22. c2.showCitation();
  23. System.out.println(c1 == c2);
  24. /**
  25. *
  26. * 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
  27. *
  28. * 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
  29. */
  30. }
  31. public static void test2() throws CloneNotSupportedException {
  32. //1,create prototype object
  33. Citation c1 = new Citation();
  34. //2,clone prototype object
  35. Citation c2 = c1.clone();
  36. //3,set variable value
  37. c1.setName("zhangSan");
  38. c2.setName("lisi");
  39. c1.showCitation();
  40. c2.showCitation();
  41. System.out.println(c1 == c2);
  42. /**
  43. *
  44. * 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原
  45. * 有属性所指向的对象的内存地址。
  46. *
  47. * 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
  48. */
  49. }
  50. }

4,深克隆案例

4.1,案例一(浅克隆)

image.png
image.png

4.1.1,克隆接口(抽象原型类)

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/29 14:51
  4. * @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo1.abstractObject
  5. * @ClassName: CitationPrototype
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public abstract class CitationPrototype implements Cloneable{
  10. }

4.1.2,具体原型类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/29 14:53
  4. * @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo1.specificObject
  5. * @ClassName: Citation
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Citation extends CitationPrototype {
  10. private Student stu ;
  11. public Student getStu() {
  12. return stu;
  13. }
  14. public void setStu(Student stu) {
  15. this.stu = stu;
  16. }
  17. public void show(){
  18. System.out.println(stu.getStuName() + " 同学:在2021-2022学年第一学期中表现优秀,特发此状,以资鼓励!");
  19. }
  20. @Override
  21. public Citation clone() throws CloneNotSupportedException {
  22. System.out.println("Citation object had cloned ...");
  23. return (Citation) super.clone();
  24. }
  25. }
  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/29 14:52
  4. * @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo1.specificObject
  5. * @ClassName: Student
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Student {
  10. private String stuName ;
  11. private String address ;
  12. public Student(String stuName, String address) {
  13. this.stuName = stuName;
  14. this.address = address;
  15. }
  16. public String getAddress() {
  17. return address;
  18. }
  19. public void setAddress(String address) {
  20. this.address = address;
  21. }
  22. public String getStuName() {
  23. return stuName;
  24. }
  25. public void setStuName(String stuName) {
  26. this.stuName = stuName;
  27. }
  28. }

4.1.3,访问类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/29 14:56
  4. * @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo1
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) throws CloneNotSupportedException {
  11. //浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性(Student.stuName),仍指向原有属性所指向的对象的内存地址。
  12. Student stu1 = new Student("zhangSan", "十堰");
  13. Citation c1 = new Citation();
  14. c1.setStu(stu1);
  15. Citation c2 = c1.clone();
  16. Student stu2 = c2.getStu();
  17. stu2.setStuName("lisi");//c2对象是从c1克隆过来的,stu2是非基本类型,修改stu2的属性值,也会把stu1的进行修改
  18. System.out.println(stu1 == stu2);
  19. c1.show();
  20. c2.show();
  21. /**stu对象和stu1对象是同一个对象,就会产生将stu1对象中name属性值改为“李四”,两个
  22. Citation(奖状)对象中显示的都是李四。这就是浅克隆的效果,对具体原型类(Citation)中的
  23. 引用类型的属性进行引用的复制。这种情况需要使用深克隆,而进行深克隆需要使用对象流
  24. */
  25. }
  26. }

4.2,案例二

image.png
image.png

4.2.1,原型接口(抽象原型类)

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/29 14:51
  4. * @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo1.abstractObject
  5. * @ClassName: CitationPrototype
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public abstract class CitationPrototype implements Cloneable{
  10. }

4.2.2,具体原型类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/29 14:53
  4. * @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo1.specificObject
  5. * @ClassName: Citation
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Citation extends CitationPrototype implements Serializable {
  10. private Student stu ;
  11. public Student getStu() {
  12. return stu;
  13. }
  14. public void setStu(Student stu) {
  15. this.stu = stu;
  16. }
  17. public void show(){
  18. System.out.println(stu.getStuName() + " 同学:在2021-2022学年第一学期中表现优秀,特发此状,以资鼓励!");
  19. }
  20. @Override
  21. public Citation clone() throws CloneNotSupportedException {
  22. System.out.println("Citation object had cloned ...");
  23. return (Citation) super.clone();
  24. }
  25. }
  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/29 14:52
  4. * @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo2.specificObject
  5. * @ClassName: Student
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Student implements Serializable {
  10. private String stuName ;
  11. private String address ;
  12. public Student(String stuName, String address) {
  13. this.stuName = stuName;
  14. this.address = address;
  15. }
  16. public String getAddress() {
  17. return address;
  18. }
  19. public void setAddress(String address) {
  20. this.address = address;
  21. }
  22. public String getStuName() {
  23. return stuName;
  24. }
  25. public void setStuName(String stuName) {
  26. this.stuName = stuName;
  27. }
  28. }

4.2.3,访问类

  1. /**
  2. * @Author zhou_ge
  3. * @Date 2022/6/29 15:06
  4. * @PackageName:xyz.zhouge.designPatterns.prototype.deep_clone.demo2
  5. * @ClassName: Client
  6. * @Description: TODO
  7. * @Version 1.0
  8. */
  9. public class Client {
  10. public static void main(String[] args) throws Exception {
  11. shallow_clone();
  12. System.out.println("======================");
  13. deep_clone();
  14. }
  15. public static void shallow_clone() throws Exception {
  16. //浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性(Student.stuName),仍指向原有属性所指向的对象的内存地址。
  17. Student stu1 = new Student("zhangSana", "十堰");
  18. Citation c1 = new Citation();
  19. c1.setStu(stu1);
  20. Citation c2 = c1.clone();
  21. Student stu2 = c2.getStu();
  22. stu2.setStuName("lisi");//c2对象是从c1克隆过来的,stu2是非基本类型,修改stu2的属性值,也会把stu1的进行修改
  23. System.out.println(stu1 == stu2);
  24. c1.show();
  25. c2.show();
  26. /**stu对象和stu1对象是同一个对象,就会产生将stu1对象中name属性值改为“李四”,两个
  27. Citation(奖状)对象中显示的都是李四。这就是浅克隆的效果,对具体原型类(Citation)中的
  28. 引用类型的属性进行引用的复制。这种情况需要使用深克隆,而进行深克隆需要使用对象流
  29. */
  30. }
  31. public static void deep_clone() throws Exception {
  32. //1,创建citaion对象
  33. Student stu1 = new Student("zhangSan", "shiyan");
  34. Citation c1 = new Citation();
  35. c1.setStu(stu1);
  36. //2,写入对象
  37. ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("H:\\desktop\\temp.txt"));
  38. oos.writeObject(c1);
  39. oos.close();
  40. //3,读取对象
  41. ObjectInputStream ois = new ObjectInputStream(new FileInputStream("H:\\desktop\\temp.txt"));
  42. Citation c2 = (Citation) ois.readObject();
  43. Student stu2 = c2.getStu();
  44. stu2.setStuName("lisi");
  45. c1.show();
  46. c2.show();
  47. System.out.println(stu1 == stu2);
  48. }
  49. }

四、建造者模式

将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。
-分离了部件的构造(由Builder来负责)和装配(由Director负责)。 从而可以构造出复杂的对象。这个模式适用于:某个对象的构建过程复杂的情况。
-由于实现了构建和装配的解耦。不同的构建器,相同的装配,也可以做出不同的对象;相同的构建器,不同的装配顺序也可以做出不同的对象。也就是实现了构建算法、装配算法的解耦,实现了更好的复用。
-建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象。用户只需要指定复杂对象的类型就可以得到该对象,而无须知道其内部的具体构造细节。

1,建造者模式的结构

建造者(Builder)模式包含如下角色:
抽象建造者类(Builder):这个接口规定要实现复杂对象的那些部分的创建,并不涉及具体的部件对象的创建。
具体建造者类(ConcreteBuilder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。在构造过程完成后,提供产品的实例。
产品类(Product):要创建的复杂对象。
指挥者类(Director):调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。
image.png

2,建造者模式案例

【创建共享单车】
生产自行车是一个复杂的过程,它包含了车架,车座等组件的生产。而车架又有碳纤维,铝合金等材质的,车座有橡胶,真皮等材质。对于自行车的生产就可以使用建造者模式。
这里Bike是产品,包含车架,车座等组件;Builder是抽象建造,MobikeBuilder和OfoBuilder是具体的建造者;Director是指挥者。
image.png

3,扩展