05原型与单例模式

原型模式

  • 定义:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象

    • 备注
      1. 通过克隆方法所创建的对象是全新的对象,它们在内存中拥有新的地址
      2. 通过不同的方式对克隆对象进行修改以后,可以得到一系列相似但不完全相同的对象
  • 简单结构:3个角色

    1. Prototype(抽象原型类)
    2. ConcretePrototype(具体原型类)
    3. Client(客户类)
  • UML图
    Pasted image 20230313085605

  • 拓展:浅克隆与深克隆

  1. 浅克隆(Shallow Clone):当原型对象被复制时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制

Pasted image 20230313085904

- 在代码中使用clone()方法实现浅克隆
  1. 深克隆(Deep Clone):除了对象本身被复制外,对象所包含的所有成员变量也将被复制

Pasted image 20230313085959

- 在代码中使用实现Serializable接口实现深克隆
  • 原型管理器:原型管理器(Prototype Manager)将多个原型对象存储在一个集合中供客户端使用,它是一个专门负责克隆对象的工厂,其中定义了一个集合用于存储原型对象,如果需要某个原型对象的一个克隆,可以通过复制集合中对应的原型对象来获得
    Pasted image 20230313093540

  • 优缺点

    1. 优点:
      • 简化对象的创建过程
      • 扩展性较好
      • 提供了简化的创建结构
      • 可以使用深克隆的方式保存对象的状态
    2. 缺点:
      • 需要为每一个类配备一个克隆方法
      • 实现深克隆时需要编写较为复杂的代码
  • 适用环境

    1. 创建新对象成本较大,新对象可以通过复制已有对象来获得,如果是相似对象,则可以对其成员变量稍作修改
    2. 系统要保存对象的状态,而对象的状态变化很小
    3. 需要避免使用分层次的工厂类来创建分层次的对象

单例模式

  • 定义:确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。

  • 要点:某个类只能有一个实例;必须自行创建这个实例;必须自行向整个系统提供这个实例

  • 简单结构:一个单例角色
    1.Singleton(单例)

  • UML图
    Pasted image 20230313094527

Pasted image 20230313095834

  • 拓展:饿汉式单例与懒汉式单例
  1. 饿汉式单例类(Eager Singleton)
    Pasted image 20230313095834
public class EagerSingleton { 
    private static final EagerSingleton instance = new EagerSingleton(); 
    private EagerSingleton() { } 
 
    public static EagerSingleton getInstance() {
        return instance; 
    }
}

  1. 懒汉式单例类(Lazy Singleton)
    Pasted image 20230313100320
public class LazySingleton { 
private static LazySingleton instance = null; 
 
private LazySingleton() { } 
 
	public static LazySingleton getInstance() { 
		if (instance == null) {
			instance = new LazySingleton(); 
		}
		return instance; 
	}
}

注意:如果多个线程同时访问将导致创建多个单例对象!怎么办?

双重检查锁

  1. 锁方法
public class LazySingleton { 
private static LazySingleton instance = null; 
 
private LazySingleton() { } 
 
	synchronized public static LazySingleton getInstance() { 
		if (instance == null) {
			instance = new LazySingleton(); 
		}
		return instance; 
	}
}

  1. 锁代码段
...
public static LazySingleton getInstance() { 
    if (instance == null) {
        synchronized (LazySingleton.class) {
            instance = new LazySingleton(); 
        }
    }
    return instance; 
}
...
  1. 双重检查锁定
public class LazySingleton { 
    private volatile static LazySingleton instance = null; 

    private LazySingleton() { } 

    public static LazySingleton getInstance() { 
        //第一重判断
        if (instance == null) {
            //锁定代码块
            synchronized (LazySingleton.class) {
                //第二重判断
                if (instance == null) {
                    instance = new LazySingleton(); //创建单例实例
                }
            }
        }
    return instance; 
    }

  • 区别:

    1. 饿汉式单例类:无须考虑多个线程同时访问的问题;调用速度和反应时间优于懒汉式单例;资源利用效率不及懒汉式单例;系统加载时间可能会比较长
    2. 懒汉式单例类:实现了延迟加载;必须处理好多个线程同时访问的问题;需通过双重检查锁定等机制进行控制,将导致系统性能受到一定影响
  • 优缺点

    1. 优点:
      • 提供了对唯一实例的受控访问
      • 可以节约系统资源,提高系统的性能
      • 允许可变数目的实例(多例类)
    2. 缺点:
      • 扩展困难(缺少抽象层)
      • 单例类的职责过重
      • 由于自动垃圾回收机制,可能会导致共享的单例对象的状态丢失
  • 适用环境

    1. 系统只需要一个实例对象,或者因为资源消耗太大而只允许创建一个对象
    2. 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例
posted @   vbig  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示
主题色彩