questions
设计模式六大原则
开闭原则:软件实体(类、函数、模块)对扩展开放,对修改封闭
单一职责:每个类只做它负责的事情(一个类应该只有一个引起它修改的原因)
里氏替换:子类可以完全代替父类
依赖倒置:细节依赖于抽象,抽象不依赖于细节,程序细节由底层完成
最少知道:迪米特法则,尽量降低类与类之间的耦合。一个类不应该知道自己操作的类的细节
接口隔离:一个接口实现时,如果有冗余,就应该把接口拆分,让实现的类只依赖自己需要的接口,客户端不应依赖于它不知道的接口
创造型模式
1 | 工厂方法模式:为每一类对象建立工厂,将对象交由工厂创建,客户端只和工厂打交道。 |
饿汉:变量在声明时便初始化,但饿汉式有一个弊端,那就是即使这个单例不需要使用,它也会在类加载之后立即创建出来,占用一块内存,并增加类初始化时间。
懒汉:先声明一个空变量,需要用时才初始化。懒汉式解决了饿汉式的弊端,好处是按需加载,避免了内存浪费,减少了类初始化时间。
- 但是懒汉不是线程安全的,要实现线程安全的懒汉,需要加同步锁
1 | import "sync"// 同步包 |
工厂模式
抽象工厂模式
单例模式
建造者模式
原型模式
结构型模式
1 | 适配器模式:用于有相关性但不兼容的接口 |
适配器模式
装饰器模式
代理模式
享元模式:享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。
FlyWeightFactory负责创建和管理享元单元,当一个客户端请求时,工厂需要检查当前对象池中是否有符合条件的对象,如果有,就返回已经存在的对象,如果没有,则创建一个新对象,FlyWeight是超类。
一提到共享池,我们很容易联想到Java里面的JDBC连接池,想想每个连接的特点,我们不难总结出:适用于作共享的一些个对象,他们有一些共有的属性,就拿数据库连接池来说,url、driverClassName、username、password及dbname,这些属性对于每个连接来说都是一样的,所以就适合用享元模式来处理,建一个工厂类,将上述类似属性作为内部数据,其它的作为外部数据,在方法调用时,当做参数传进来,这样就节省了空间,减少了实例的数量。
外观模式
桥接模式
组合模式
行为型模式
1 | 行为型模式重点关注类与类之间的交互与协作。如同在工作中,每个人的行为都可能影响到其他同事,同时每个人也会受到别人的影响。我们一边接收上级的指令,一边派发任务给下级,在这样的协作中完成一项项伟大的工作。程序在运行时,每个对象都不是孤立的,他们可以通过通信与协作完成种种复杂的功能。 |
责任链模式:责任链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止
观察者模式
中介者模式
访问者模式
解释器模式
迭代器模式
命令模式
备忘录模式
面试问题
- 面向对象的特点是什么?
可维护、可复用、可扩展、灵活性好。
- 让面向对象保持结构良好的秘诀是什么?
让面向对象保持结构良好的秘诀就是设计模式,面向对象结合设计模式,才能真正体会到程序变得可维护、可复用、可扩展、灵活性好。
- 六大设计原则是什么?
开闭原则、单一职责原则、里氏替换原则、依赖倒置原则、迪米特原则、接口隔离原则。
- 什么是里氏替换原则?
子类应该可以完全替换父类。也就是说在使用继承时,只扩展新功能,而不要破坏父类原有的功能。
- 工厂模式是用于达到什么目的的设计模式?
封装对象。
- 工厂模式有哪三种?
简单工厂模式、工厂方法模式、抽象工厂模式。
- 工厂方法模式解决了简单工厂模式的哪两个弊端?
当生产的产品种类越来越多时,工厂类不会变成超级类。工厂类会越来越多,保持灵活。不会越来越大、变得臃肿。如果苹果的生产过程需要修改时,只需修改苹果工厂。梨子的生产过程需要修改时,只需修改梨子工厂。符合单一职责原则。
当需要生产新的产品时,无需更改既有的工厂,只需要添加新的工厂即可。保持了面向对象的可扩展性,符合开闭原则。
- 抽象工厂模式是什么样的?
在创建时指定了具体的工厂类后,在使用时就无需再关心是哪个工厂类,只需要将此工厂当作抽象的 IFactory 接口使用即可。这种经过抽象的工厂方法模式被称作抽象工厂模式。
- 抽象工厂模式很好的发挥了哪些原则?
开闭原则、依赖倒置原则。
- 抽象工厂模式的缺点是什么?
缺点是抽象工厂模式太重了,如果 IFactory 接口需要新增功能,则会影响到所有的具体工厂类。使用抽象工厂模式,替换具体工厂时只需更改一行代码,但要新增抽象方法则需要修改所有的具体工厂类。
- 抽象工厂模式适用于和不适用于哪些情况?
适用于增加同类工厂这样的横向扩展需求,不适合新增功能这样的纵向扩展。
- 什么时候可以使用单例模式?
某个对象全局只需要一个实例时即可。
- 单例模式的优点是什么?
• 它能够避免对象重复创建,节约空间并提升效率
• 避免由于操作不同实例导致的逻辑错误
- 单例模式有哪两种实现方式?请分别简单解释。
饿汉式和懒汉式。饿汉式指变量在声明时便初始化。懒汉式指先声明一个空变量,需要用时才初始化。
- 饿汉式的弊端是什么?
即使这个单例不需要使用,它也会在类加载之后立即创建出来,占用一块内存,并增加类初始化时间。
- 静态内部类方式是怎么保证线程安全的?
Java 虚拟机的设计是非常稳定的,早已经考虑到了多线程并发执行的情况。虚拟机在加载类的 clinit 方法时,会保证 clinit 在多线程中被正确的加锁、同步。即使有多个线程同时去初始化一个类,一次也只有一个线程可以执行 clinit 方法,其他线程都需要阻塞等待,从而保证了线程安全。
- 建造者模式用于什么时候?
创建过程稳定,但配置多变的对象。
- 建造者模式是什么意思?
将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
- 现在建造者模式主要用来做什么?
通过链式调用生成不同的配置。
- 使用建造者模式的好处是什么?
不用担心忘了指定某个配置,保证了构建过程是稳定的。
- 原型模式是什么?
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
- 适配器模式适用于什么结构?
有相关性但不兼容的结构。
- 什么是适配?什么是适配器?
源接口通过一个中间件转换后才可以适用于目标接口,这个转换过程就是适配,这个中间件就称之为适配器。
- 需要绘制矩形、圆形、三角形这三种图案,按照桥接模式的思想会怎么做?
将形状和颜色分离,根据需要对形状和颜色进行组合。
- 什么是桥接模式?
将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体模式或接口模式。
- 组合模式适用于什么结构?
组合模式用于整体与部分的结构,当整体与部分有相似的结构,在操作时可以被一致对待时,就可以使用组合模式。
- 组合模式最主要的功能是什么?
组合模式最主要的功能是让用户可以一致对待整体和部分结构,将两者都作为一个相同的组件。
- 什么是组合模式中的透明方式?
违背了接口隔离原则的组合模式。
- 什么是安全方式?
在 Component 中不声明 add 和 remove 等管理子对象的方法,这样叶节点就无需实现它,只需在枝节点中实现管理子对象的方法即可。
- 什么是透明装饰模式?
装饰器仅用于增强功能,并不会改变 Me 原有的功能,这种装饰模式称之为透明装饰模式。
- 装饰模式的缺点是什么?
容易造成程序中有大量相似的类。
- 动态代理相对于静态代理的优势是什么?
节省代码量。
- 简述责任链模式的有优点有哪些?
• 降低了对象之间的耦合度。
• 扩展性强,满足开闭原则。可以根据需要增加新的请求处理类。
• 灵活性强。可以动态地改变链内的成员或者改变链的次序来适应流程的变化。
• 简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用。
- 什么是宏命令?
宏命令是将多个命令合并起来组成的命令。
- 请写出解释器模式的一个常见应用。
在我们平时匹配字符串时,用到的正则表达式就是一个解释器。
- 怎样使得外部类只能读取此列表中的数据,无法修改其中的任何数据,保证其安全性?
• 提供一个 String next() 方法,使得外部类可以按照次序,一条一条的读取数据;
• 提供一个 boolean hasNext() 方法,告知外部类是否还有下一条数据。