questions

设计模式六大原则

开闭原则:软件实体(类、函数、模块)对扩展开放,对修改封闭

单一职责:每个类只做它负责的事情(一个类应该只有一个引起它修改的原因)
里氏替换:子类可以完全代替父类

依赖倒置:细节依赖于抽象,抽象不依赖于细节,程序细节由底层完成

最少知道:迪米特法则,尽量降低类与类之间的耦合。一个类不应该知道自己操作的类的细节

接口隔离:一个接口实现时,如果有冗余,就应该把接口拆分,让实现的类只依赖自己需要的接口,客户端不应依赖于它不知道的接口

创造型模式

1
2
3
4
5
工厂方法模式:为每一类对象建立工厂,将对象交由工厂创建,客户端只和工厂打交道。
抽象工厂模式:为每一类工厂提取出抽象接口,使得新增工厂、替换工厂变得非常容易。
建造者模式:用于创建构造过程稳定的对象,不同的 Builder 可以定义不同的配置。
单例模式:全局使用同一个对象,分为饿汉式和懒汉式。懒汉式有双检锁和内部类两种实现方式。
原型模式:为一个类定义 clone 方法,使得创建相同的对象更方便。

饿汉:变量在声明时便初始化,但饿汉式有一个弊端,那就是即使这个单例不需要使用,它也会在类加载之后立即创建出来,占用一块内存,并增加类初始化时间。
懒汉:先声明一个空变量,需要用时才初始化。懒汉式解决了饿汉式的弊端,好处是按需加载,避免了内存浪费,减少了类初始化时间。
- 但是懒汉不是线程安全的,要实现线程安全的懒汉,需要加同步锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import "sync"// 同步包
type Singleton struct{

}
//饿汉
var instance *Singleton = &Singleton{}
func getInstance() *Singleton{
return instance
}
//懒汉线程安全
var once sync.Once
func getInstance() *Singleton{
once.Do(func(){
instance := &Singleton{}
})
return instance
}

工厂模式
抽象工厂模式
单例模式
建造者模式
原型模式

结构型模式

1
2
3
4
5
6
适配器模式:用于有相关性但不兼容的接口
桥接模式:用于同等级的接口互相组合
组合模式:用于整体与部分的结构
外观模式:体现封装的思想
享元模式:体现面向对象的可复用性
代理模式:主要用于对某个对象加以控制

适配器模式
装饰器模式
代理模式
享元模式:享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。

FlyWeightFactory负责创建和管理享元单元,当一个客户端请求时,工厂需要检查当前对象池中是否有符合条件的对象,如果有,就返回已经存在的对象,如果没有,则创建一个新对象,FlyWeight是超类。
一提到共享池,我们很容易联想到Java里面的JDBC连接池,想想每个连接的特点,我们不难总结出:适用于作共享的一些个对象,他们有一些共有的属性,就拿数据库连接池来说,url、driverClassName、username、password及dbname,这些属性对于每个连接来说都是一样的,所以就适合用享元模式来处理,建一个工厂类,将上述类似属性作为内部数据,其它的作为外部数据,在方法调用时,当做参数传进来,这样就节省了空间,减少了实例的数量。

外观模式
桥接模式
组合模式

行为型模式

1
2
3
4
5
6
7
8
9
10
11
12
13
行为型模式重点关注类与类之间的交互与协作。如同在工作中,每个人的行为都可能影响到其他同事,同时每个人也会受到别人的影响。我们一边接收上级的指令,一边派发任务给下级,在这样的协作中完成一项项伟大的工作。程序在运行时,每个对象都不是孤立的,他们可以通过通信与协作完成种种复杂的功能。

责任链模式:处理职责相同,程度不同的对象,使其在一条链上传递
命令模式:封装“方法调用”,将行为请求者和行为实现者解耦
解释器模式:定义自己的语法规则
迭代器模式:定义 next() 方法和 hasNext() 方法,让外部类使用这两个方法来遍历列表,以达到隐藏列表内部细节的目的
中介者模式:通过引入中介者,将网状耦合结构变成星型结构
备忘录模式:存储对象的状态,以便恢复
观察者模式:处理一对多的依赖关系,被观察的对象改变时,多个观察者都能收到通知
状态模式:关于多态的设计模式,每个状态类处理对象的一种状态
策略模式:殊途同归,用多种方法做同一件事
模板方法模式:关于继承的设计模式,父类是子类的模板
访问者模式:将数据的结构和对数据的操作分离

责任链模式:责任链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止
观察者模式
中介者模式
访问者模式
解释器模式
迭代器模式
命令模式
备忘录模式

面试问题

  1. 面向对象的特点是什么?

可维护、可复用、可扩展、灵活性好。

  1. 让面向对象保持结构良好的秘诀是什么?

让面向对象保持结构良好的秘诀就是设计模式,面向对象结合设计模式,才能真正体会到程序变得可维护、可复用、可扩展、灵活性好。

  1. 六大设计原则是什么?

开闭原则、单一职责原则、里氏替换原则、依赖倒置原则、迪米特原则、接口隔离原则。

  1. 什么是里氏替换原则?

子类应该可以完全替换父类。也就是说在使用继承时,只扩展新功能,而不要破坏父类原有的功能。

  1. 工厂模式是用于达到什么目的的设计模式?

封装对象。

  1. 工厂模式有哪三种?

简单工厂模式、工厂方法模式、抽象工厂模式。

  1. 工厂方法模式解决了简单工厂模式的哪两个弊端?

当生产的产品种类越来越多时,工厂类不会变成超级类。工厂类会越来越多,保持灵活。不会越来越大、变得臃肿。如果苹果的生产过程需要修改时,只需修改苹果工厂。梨子的生产过程需要修改时,只需修改梨子工厂。符合单一职责原则。
当需要生产新的产品时,无需更改既有的工厂,只需要添加新的工厂即可。保持了面向对象的可扩展性,符合开闭原则。

  1. 抽象工厂模式是什么样的?

在创建时指定了具体的工厂类后,在使用时就无需再关心是哪个工厂类,只需要将此工厂当作抽象的 IFactory 接口使用即可。这种经过抽象的工厂方法模式被称作抽象工厂模式。

  1. 抽象工厂模式很好的发挥了哪些原则?

开闭原则、依赖倒置原则。

  1. 抽象工厂模式的缺点是什么?

缺点是抽象工厂模式太重了,如果 IFactory 接口需要新增功能,则会影响到所有的具体工厂类。使用抽象工厂模式,替换具体工厂时只需更改一行代码,但要新增抽象方法则需要修改所有的具体工厂类。

  1. 抽象工厂模式适用于和不适用于哪些情况?

适用于增加同类工厂这样的横向扩展需求,不适合新增功能这样的纵向扩展。

  1. 什么时候可以使用单例模式?

某个对象全局只需要一个实例时即可。

  1. 单例模式的优点是什么?

• 它能够避免对象重复创建,节约空间并提升效率
• 避免由于操作不同实例导致的逻辑错误

  1. 单例模式有哪两种实现方式?请分别简单解释。

饿汉式和懒汉式。饿汉式指变量在声明时便初始化。懒汉式指先声明一个空变量,需要用时才初始化。

  1. 饿汉式的弊端是什么?

即使这个单例不需要使用,它也会在类加载之后立即创建出来,占用一块内存,并增加类初始化时间。

  1. 静态内部类方式是怎么保证线程安全的?

Java 虚拟机的设计是非常稳定的,早已经考虑到了多线程并发执行的情况。虚拟机在加载类的 clinit 方法时,会保证 clinit 在多线程中被正确的加锁、同步。即使有多个线程同时去初始化一个类,一次也只有一个线程可以执行 clinit 方法,其他线程都需要阻塞等待,从而保证了线程安全。

  1. 建造者模式用于什么时候?

创建过程稳定,但配置多变的对象。

  1. 建造者模式是什么意思?

将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

  1. 现在建造者模式主要用来做什么?

通过链式调用生成不同的配置。

  1. 使用建造者模式的好处是什么?

不用担心忘了指定某个配置,保证了构建过程是稳定的。

  1. 原型模式是什么?

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

  1. 适配器模式适用于什么结构?

有相关性但不兼容的结构。

  1. 什么是适配?什么是适配器?

源接口通过一个中间件转换后才可以适用于目标接口,这个转换过程就是适配,这个中间件就称之为适配器。

  1. 需要绘制矩形、圆形、三角形这三种图案,按照桥接模式的思想会怎么做?

将形状和颜色分离,根据需要对形状和颜色进行组合。

  1. 什么是桥接模式?

将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体模式或接口模式。

  1. 组合模式适用于什么结构?

组合模式用于整体与部分的结构,当整体与部分有相似的结构,在操作时可以被一致对待时,就可以使用组合模式。

  1. 组合模式最主要的功能是什么?

组合模式最主要的功能是让用户可以一致对待整体和部分结构,将两者都作为一个相同的组件。

  1. 什么是组合模式中的透明方式?

违背了接口隔离原则的组合模式。

  1. 什么是安全方式?

在 Component 中不声明 add 和 remove 等管理子对象的方法,这样叶节点就无需实现它,只需在枝节点中实现管理子对象的方法即可。

  1. 什么是透明装饰模式?

装饰器仅用于增强功能,并不会改变 Me 原有的功能,这种装饰模式称之为透明装饰模式。

  1. 装饰模式的缺点是什么?

容易造成程序中有大量相似的类。

  1. 动态代理相对于静态代理的优势是什么?

节省代码量。

  1. 简述责任链模式的有优点有哪些?

• 降低了对象之间的耦合度。
• 扩展性强,满足开闭原则。可以根据需要增加新的请求处理类。
• 灵活性强。可以动态地改变链内的成员或者改变链的次序来适应流程的变化。
• 简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用。

  1. 什么是宏命令?

宏命令是将多个命令合并起来组成的命令。

  1. 请写出解释器模式的一个常见应用。

在我们平时匹配字符串时,用到的正则表达式就是一个解释器。

  1. 怎样使得外部类只能读取此列表中的数据,无法修改其中的任何数据,保证其安全性?

• 提供一个 String next() 方法,使得外部类可以按照次序,一条一条的读取数据;
• 提供一个 boolean hasNext() 方法,告知外部类是否还有下一条数据。