设计模式

建造者模式

1、什么是建造者模式
建造者模式: 是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的方式进行创建。
工厂类模式是提供的是创建单个类的产品
而建造者模式则是将各种产品集中起来进行管理,用来具有不同的属性的产品

建造者模式通常包括下面几个角色:

1、 uilder: 给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。ConcreteBuilder: 实现 Builder 接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例。3、Director: 调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。Product: 要创建的复杂对象。

2、建造者模式的使用场景
使用场景:

需要生成的对象具有复杂的内部结构
需要生成的对象内部属性本身相互依赖。
与工厂模式的区别是: 建造者模式更加关注与零件装配的顺序。

JAVA 中的 StringBuilder就是建造者模式创建的,他把一个单个字符的 char数组组合起来。Spring 不是建造者模式,它提供的操作应该是对于字符串本身的一些操作,而不是创建或改变一个字符串。

单例模式

1、关于单例模式,谈谈你的了解吧
(1)单例模式是一种常用的设计模式,单例模式比较简单但包含了关于线程安全、内存模型、类加载机制等一些比较核心的知识点。

(2)单例模式就是在整个运行时域,一个类只有一个实例对象。

(3)为什么需要单例模式呢?因为有的类型的实例对象的创建和销毁对资源来说消耗不大,比如string,然而有的类型呢就比较复杂庞大,如果频繁的创建和销毁对象并且这些对象完全是可以复用的话,那么将会造成一些不必要的性能浪费。

(4)举个例子吧,比如我现在要写一个访问数据库的demo,而创建数据库链接对象是一个耗资源的操作并且数据库链接完全是可以复用的,那么我可以将这个对象设计成单例的,这样我只要创建一次并且重复使用这个对象就可以了,而不是每次都要去访问数据库去创建一个链接对象。
3、实现java单例模式的几种模式?
(1)饿汉式一静态常量方式(线程安全):

类加载时就初始化实例,避免了多线程同步问题,天然线程安全。

(2)饿汉式一静态代码块方式

(线程安全:其实就是在静态常量饿汉式实现上稍微变动了一下,将类的实例化放在了静态代码块中而已,其他没区别。

(3)懒汉式(线程不安全)

这是最基本的实现方式,第一次调用才初始化,实现了懒加载的特性。多线程场景下禁止使用,因为可能会产生多个对象,不再是单例。

(4)懒汉式(线程安全,方法上加同步锁)

线程不安全懒汉式实现上唯一不同是:获取实例的getInstance0方法上加了同步锁。保证了多线程场景下的单例。但是效率会有所折损,不过还好。

(5)双重校验锁(线程安全,效率高)

此种实现中不用每次需要获得锁,减少了获取锁和等待的事件。注意volatile关键字的使用,保证了各线程对singleton静态实例域修改的可见性。

(6)静态内部类实现单例(线程安全、效率高)

这种方式下Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有通过显式调用getInstance方法时,才会显式装载SingletonHolder类,从而实例化instance.。

4、java单例模式的基本特点?
答:持有自己类型的属性:类构造器私有:对外提供获取实例的静态方法。

5、饿汉式和懒汉式的区别?
(1)线程安全方面:饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,懒汉式本身是非线程安全的。

(2)资源加载和性能方面:饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成,而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。

工厂模式

001什么是工厂设计模式?
工厂模式提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。实现了创建者和调用者分离,工厂模式分为简单工厂、工厂方法、抽象工厂模式。

002什么是简单工厂模式?
简单工厂模式又叫静态方法模式(因为工厂类定义了一个静态方法)现实生活中,工厂是负责生产产品的;同样在设计模式中,简单工厂模式我们可以理解为负责生产对象的一个类,称为“工厂类”。

003简单工厂模式解决的问题?
将“类实例化的操作”与“使用对象的操作”分开,让使用者不用知道具体参数就可以实例化出所需要的“产品”类,从而避免了在客户端代码中显式指定,实现了解耦。即使用者可直接消费产品而不需要知道其生产的细节

004简单工厂设计模式的实现。
简单工厂模式:把对象的创建放到一个工厂类中,通过参数来创建不同的对象。

005简单工厂模式的优点?
将创建实例的工作与使用实例的工作分开,使用者不必关心类对象如何创建,实现了解耦;
把初始化实例时的工作放到工厂里进行,使代码更容易维护。 更符合面向对象的原则 & 面向接口编程,而不是面向实现编程。

006简单工厂模式的缺点?
1)工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响;
2)违背“开放 - 关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂。
3)简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的等级结构。

007简单工厂模式的应用场景?
客户如果只知道传入工厂类的参数,对于如何创建对象的逻辑不关心时;
当工厂类负责创建的对象(具体产品)比较少时。

008什么是工厂方法模式?
工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。

009工厂方法模式的具体实现。
工厂方法模式: 每种产品由一种工厂来创建,一个工厂处理一个对象。
角色组成

  1. 抽象工厂: 定义工厂类所具有的基本的操作
  2. 具体工厂:该类必须继承抽象工厂,实现抽象工厂定义的方法,返回一个对象
  3. 抽象产品:定义了抽象产品具有的基本操作
  4. 产品实现类:实现抽象产品类对定义的抽象方法,和具体工厂一一对应;
    010工厂方法模式解决的问题?
    工厂方法模式把具体产品的创建推迟到工厂类的子类(具体工厂)中,此时工厂类不再负责所有产品的创建,而只是给出具体工厂必须实现的接口,这样工厂方法模式在添加新产品的时候就不修改工厂类逻辑而是添加新的工厂子类,符合开放封闭原则,克服了简单工厂模式中缺点。

011工厂方法模式的优点?
1)更符合开-闭原则
新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可
简单工厂模式需要修改工厂类的判断逻辑
2)符合单一职责原则
每个具体工厂类只负责创建对应的产品
简单工厂中的工厂类存在复杂的switch逻辑判断
3)不使用静态工厂方法,可以形成基于继承的等级结构。
简单工厂模式的工厂类使用静态工厂方法
总结:工厂模式可以说是简单工厂模式的进一步抽象和拓展,在保留了简单工厂的封装优点的同时,让扩展变得简单,让继承变得可行,增加了多态性的体现。

012工厂方法模式的缺点?
1)添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销;
2)由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。
3)虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类;一个具体工厂只能创建一种具体产品。

013工厂方法模式的应用场景。
1)当一个类不知道它所需要的对象的类时,在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可;
2)当一个类希望通过其子类来指定创建对象时,在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
3)将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。

014什么是抽象工厂模式?
抽象工厂模式,即Abstract Factory Pattern,提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类;具体的工厂负责实现具体的产品实例。 允许使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么,这样就可以从具体产品中被解耦。

015抽象工厂模式的具体实现。
抽象工厂模式:工厂方法模式的进一步延伸。
角色组成

  1. 抽象工厂: 定义工厂类所具有的基本的操作
  2. 具体工厂:具体工厂实现了抽象工厂,每个工厂方法返回多个具体对象
  3. 抽象类接口:定义了产品具有的基本操作,提供一组所有类都具有的业务方法
  4. 抽象类:用于实现抽象接口所定义的业务方法,只做抽象接口,具体由产品实现类处理
  5. 产品实现类:实现抽象产品类对定义的抽象方法,和具体工厂一对多;
    016抽象工厂模式的优点。
    1)降低耦合
    抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展;
    2)更符合开-闭原则
    新增一种产品类时,只需要增加相应的具体产品类和相应的工厂子类即可
    3)符合单一职责原则
    每个具体工厂类只负责创建对应的产品
    4)不使用静态工厂方法,可以形成基于继承的等级结构。

017抽象工厂模式的缺点。
抽象工厂模式很难支持新种类产品的变化。这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则。

018抽象工厂模式的应用场景。
1)一个系统不要求依赖产品类实例如何被创建、组合和表达的表达,这点也是所有工厂模式应用的前提。
2)这个系统有多个系列产品,而系统中只消费其中某一系列产品
3)系统要求提供一个产品类的库,所有产品以同样的接口出现,客户端不需要依赖具体实现。

019工厂模式和抽象工厂模式对比?
工厂方法模式:具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:具体工厂类可以创建多个具体产品类的实例。

原型模式

适用场景:

类初始化消耗资源较多。
new产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)。
构造函数比较复杂。
循环体中生产大量对象时。
优点:

性能优良,Java自带的原型模式是基于内存二进制流的拷贝,比直接new一个对象性能上提升了许多。
可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,简化了创建的过程。
缺点:

必须配备克隆(或者可拷贝)方法。
当对已有类进行改造的时候,需要修改代码,违反了开闭原则。
深克隆、浅克隆需要运用得当。

你可能感兴趣的:(程序员)