设计模式内容小结

面向对象基础知识

Posted by 谢玄xx on April 27, 2022

终于到了激动人心(bushi)的设计模式环节。基本的设计模式和设计思想是必须要掌握的。

Overall Description

单例模式

  • 单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。而工厂方法是用来限制实例化过程的。这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义。
  • 单例模式,属于创建类型的一种常用的软件设计模式,它提供了一种创建对象的最佳方式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例)

意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

主要解决:一个全局使用的类频繁地创建与销毁。

何时使用:当您想控制实例数目,节省系统资源的时候。

如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。

关键代码:构造函数是私有的。

显然单例模式的要点有三个:

  1. 某个类只能有一个实例;
  2. 它必须自行创建这个实例;
  3. 它必须自行向整个系统提供这个实例。

从具体实现角度来说,就是以下三点:

  1. 单例模式的类只提供私有的构造函数;
  2. 类定义中含有一个该类的静态私有对象;
  3. 该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。

单例模式的优缺点

优点

  1. 实例控制 单例模式会阻止其他对象实例化自己的单例对象的副本,从而确保所有对象都访问唯一实例。
  2. 灵活性 因为类控制了实例化过程,所以类可以灵活更改实例化过程。

缺点

  1. 开销 虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
  2. 可能的开发混淆 使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
  3. 对象生存期 不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。

懒汉式单例

  • 是否 Lazy 初始化:是
  • 是否多线程安全:否
  • 实现难度:易
  • 描述:懒汉式单例是最基本的实现方式,这种实现最大的问题就是不支持多线程(因为没有加同步锁),所以严格意义上它并不属于单例模式。
  • 优点:在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例;避免对资源的多重占用。
  • 缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
  • 使用场景: 1、要求生产唯一序列号。 2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

饿汉式单例——一个类只能创建一个对象

  • 是否 Lazy 初始化:否
  • 是否多线程安全:是
  • 实现难度:易
  • 优点:没有加锁,执行效率会提高。
  • 缺点:类加载时就初始化,浪费内存。
  • 描述:饿汉式单例比较常用,但容易产生垃圾对象。它基于 classloder 机制避免了多线程的同步问题。饿汉就是:类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了。
public class SingletonEH {
    private static SingletonEH instance = new SingletonEH();
    private SingletonEH (){}
    public static SingletonEH getInstance() {
        System.out.println("instance:"+instance);
        System.out.println("加载饿汉式....");
        return instance;
    }
}
 

工厂模式

工厂模式是最常用的设计模式之一。这种类型的设计模式也属于创建型模式,它提供了一种创建对象的最佳方式,创建过程在其子类执行。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

  • 意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
  • 主要解决:主要解决接口选择的问题。
  • 何时使用:我们明确地计划不同条件下创建不同实例时。
  • 如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
  • 工厂模式实例: 1、我需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。
  • 优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。
  • 缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。