1、什么是设计模式?
就是经过实践验证的⽤来解决特定环境下特定问题的解决⽅案
2
、设计模式⽤来⼲什么?
寻找合适的对象
决定对象的粒度
指定对象的接⼝
描述对象的实现
运⽤复⽤机制
重复使⽤经过实践验证的正确的,⽤来解决某⼀类问题的解决⽅案来达到减少⼯作
量、提⾼正确率等⽬的
3
、什么是对象粒度?
对象中⽅法的多少就是粒度
4
、基本的
Java
编程设计应遵循的规则?
⾯向接⼝编程,优先使⽤对象组合
5
、设计模式的应⽤范围
所能解决的特定的⼀类问题中
6
、简述什么是单例模式,以及他解决的问题,应⽤的环境,解决的⽅案,模式的本质
在任何时间内只有⼀个类实例存在的模式,需要有⼀个从中进⾏全局访问和维护某种
类型数据的区域的环境下使⽤单例模式,解决⽅案就是保证⼀个类只有⼀个类实例存
在,本质就是实例共⽤同⼀块内存区域
7
、简述什么是⼯⼚模式,以及他解决的问题,应⽤的环境,解决的⽅案,模式的本质
利⽤⼯⼚来解决接⼝选择的问题的模式
应⽤环境:当⼀个类⽆法预料要创建哪种类的对象或是⼀个类需要由⼦类来指定
创建的对象时,就需要⽤到⼯⼚模式
解决⽅案:定义⼀个创建对象的接⼝
,
让⼦类来决定具体实例化哪⼀个类
本质就是根据不同的情况来选择不同的接⼝
8
、述什么是值对象模式,以及他解决的问题,应⽤的环境,解决的⽅案,模式的本质
⽤来把⼀组数据封装成⼀个对象的模式
解决问题:在远程⽅法的调⽤次数增加的时候,相关的应⽤程序性能将会有很⼤的下
降
解决⽅案:使⽤值对象的时候,可以通过仅仅⼀次⽅法调⽤来取得整个对象,⽽不是
使⽤多次⽅法调⽤以得到对象中每个域的数值
本质:就是把需要传递的多个值封装成⼀个对象⼀次性传过去
10
、简述什么是
DAO
模式,以及他解决的问题,应⽤的环境,解决的⽅案,模式的本质
数据访问对象
解决问题:根据数据源不同,数据访问也不同。根据存储的类型(关系数据库、
⾯向对象数据库、纯⽂件等)和供应商实现不同,持久性存储(如数据库)的访问差
别也很⼤。如何对存储层以外的模块屏蔽这些复杂性,以提供统⼀的调⽤存储实现。
程序的分布式问题
解决⽅案:将数据访问逻辑抽象为特殊的资源,也就是说将系统资源的接⼝从
其底层访问机制中隔离出来;通过将数据访问的调⽤打包,数据访问对象可以
促进对于不同数据库类型和模式的数据访问。
DAO
的本质就是⼀层屏蔽⼀种变化
本质:分层,是系统组件和数据源中间的适配器。(⼀层屏蔽⼀种变化)
什么是开放
-
封闭法则
(OCP)
可扩展但是不可以更改已有的模块
对扩展是开放的 对修改是封闭
什么是替换法则
(LSP)
使⽤指向基类(超类)的引⽤的函数,必须能够在不知道具体派⽣类(⼦类)对象类
型的情况下使⽤
14
、如何综合使⽤我们学过的设计模式来构建合理的应⽤程序结构
是采⽤接⼝进⾏隔离,然后同时暴露值对象和⼯⼚类,如果是需要数据存储的功能,
⼜会通过
DAO
模式去与数据存储层交互。
15
、请列举出在
JDK
中⼏个常⽤的设计模式?
单例模式(
Singleton pattern
)⽤于
Runtime
,
Calendar
和其他的⼀些类中;
⼯⼚模式(
Factory pattern
)被⽤于各种不可变的类如
Boolean
,像
Boolean.valueOf
;
观察者模式(
Observer pattern
)被⽤于
Swing
和很多的事件监听中;
装饰器设计模式(
Decorator design pattern
)被⽤于多个
Java IO
类中。
16
、什么是设计模式?你是否在你的代码⾥⾯使⽤过任何设计模式?
设计模式是世界上各种各样程序员⽤来解决特定设计问题的尝试和测试的⽅法。设计
模式是代码可⽤性的延伸。
17
、
Java
中什么叫单例设计模式?请⽤
Java
写出线程安全的单例模式
单例模式重点在于在整个系统上共享⼀些创建时较耗资源的对象。整个应⽤中只维护
⼀个特定类实例,它被所有组件共同使⽤。
Java.lang.Runtime
是单例模式的经典例⼦。
从
Java 5
开始你可以使⽤枚举(
enum
)来实现线程安全的单例。
18
、在
Java
中,什么叫观察者设计模式(
observer design pattern
)?
观察者模式是基于对象的状态变化和观察者的通讯,以便他们作出相应的操作。简单
的例⼦就是⼀个天⽓系统,当天⽓变化时必须在展示给公众的视图中进⾏反映。这个
视图对象是⼀个主体,⽽不同的视图是观察者。
19
、使⽤⼯⼚模式最主要的好处是什么?在哪⾥使⽤?
⼯⼚模式的最⼤好处是增加了创建对象时的封装层次。如果你使⽤⼯⼚来创建对象,
之后你可以使⽤更⾼级和更⾼性能的实现来替换原始的产品实现或类,这不需要在调
⽤层做任何修改。
20
、举⼀个⽤
Java
实现的装饰模式
(decorator design pattern)
?它是作⽤于对象层次还
是类层次?
装饰模式增加强了单个对象的能⼒。
Java IO
到处都使⽤了装饰模式,典型例⼦就是
Buffered
系列类如
BufferedReader
和
BufferedWriter
,它们增强了
Reader
和
Writer
对
象,以实现提升性能的
Buffer
层次的读取和写⼊。
21
、在
Java
中,为什么不允许从静态⽅法中访问⾮静态变量?
Java
中不能从静态上下⽂访问⾮静态数据只是因为⾮静态变量是跟具体的对象实例关
联的,⽽静态的却没有和任何实例关联。
22
、设计⼀个
ATM
机,请说出你的设计思路?
⽐如设计⾦融系统来说,必须知道它们应该在任何情况下都能够正常⼯作。不管是断
电还是其他情况,
ATM
应该保持正确的状态(事务)
,
想想 加锁(
locking
)、事务
(
transaction
)、错误条件(
error condition
)、边界条件(
boundary condition
) 等
等。尽管你不能想到具体的设计,但如果你可以指出⾮功能性需求,提出⼀些问题,
想到关于边界条件,这些都会是很好的。
23
、在
Java
中,什么时候⽤重载,什么时候⽤重写?
如果你看到⼀个类的不同实现有着不同的⽅式来做同⼀件事,那么就应该⽤重写
(
overriding
),⽽重载(
overloading
)是⽤不同的输⼊做同⼀件事。在
Java
中,重载
的⽅法签名不同,⽽重写并不是。
24
、举例说明什么情况下会更倾向于使⽤抽象类⽽不是接⼝?
接⼝和抽象类都遵循
”
⾯向接⼝⽽不是实现编码
”
设计原则,它可以增加代码的灵活
性,可以适应不断变化的需求。下⾯有⼏个点可以帮助你回答这个问题:
在
Java
中,你只能继承⼀个类,但可以实现多个接⼝。所以⼀旦你继承了⼀个类,你
就失去了继承其他类的机会了。
接⼝通常被⽤来表示附属描述或⾏为如:
Runnable
、
Clonable
、
Serializable
等等,因此
当你使⽤抽象类来表示⾏为时,你的类就不能同时是
Runnable
和
Clonable(
注:这⾥的
意思是指如果把
Runnable
等实现为抽象类的情况
)
,因为在
Java
中你不能继承两个
类,但当你使⽤接⼝时,你的类就可以同时拥有多个不同的⾏为。
在⼀些对时间要求⽐较⾼的应⽤中,倾向于使⽤抽象类,它会⽐接⼝稍快⼀点。
如果希望把⼀系列⾏为都规范在类继承层次内,并且可以更好地在同⼀个地⽅进⾏编
码,那么抽象类是⼀个更好的选择。有时,接⼝和抽象类可以⼀起使⽤,接⼝中定义
函数,⽽在抽象类中定义默认的实现。
25
、你所知道的设计模式有哪些?
Java
中⼀般认为有
23
种设计模式,我们不需要所有的都会,但是其中常⽤的⼏种设
计模式应该去掌握。下⾯列出了所有的设计模式。需要掌握的设计模式已经单独列出
来了,当然能掌握的越多越好。
总体来说设计模式分为三⼤类:
l
创建型模式,共五种:⼯⼚⽅法模式、抽象⼯⼚模式、单例模式、建造者模式、原型
模式。
l
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、
组合模式、享元模式。
l
⾏为型模式,共⼗⼀种:策略模式、模板⽅法模式、观察者模式、迭代⼦模式、责任
链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模
式。
26
、单例设计模式?
最好理解的⼀种设计模式,分为懒汉式和饿汉式。
饿汉式:
public class
Singleton
{
//
直接创建对象
public static Singleton instance = new Singleton();
//
私有化构造函数
private Singleton() {
}
//
返回对象实例
public static Singleton getInstance() {
return instance;
}
}
懒汉式:
public class Singleton {
//
声明变量
private static volatile Singleton singleton =
null
;
//
私有构造函数
private Singleton() {
}
//
提供对外方法
public static Singleton getInstance() {
if (singleton ==
null
) {
synchronized (Singleton.class) {
if (singleton ==
null
) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
27
、⼯⼚设计模式?
⼯⼚模式分为⼯⼚⽅法模式和抽象⼯⼚模式。
⼯⼚⽅法模式分为三种:
l
普通⼯⼚模式,就是建⽴⼀个⼯⼚类,对实现了同⼀接⼝的⼀些类进⾏实例的创建。
多个⼯⼚⽅法模式,是对普通⼯⼚⽅法模式的改进,在普通⼯⼚⽅法模式中,如果传
递的字符串出错,则不能正确创建对象。
l
多个⼯⼚⽅法模式,是提供多个⼯⼚⽅法,分别创建对象。
l
静态⼯⼚⽅法模式,将上⾯的多个⼯⼚⽅法模式⾥的⽅法置为静态的,不需要创建实
例,直接调⽤即可。
n
普通⼯⼚模式
public interface
Sender
{
public void
Send
();
}
public class
MailSender
implements
Sender
{
@Override
public void
Send
() {
System.out.println(
"this is mail sender!"
);
}
}
public class
SmsSender
implements
Sender
{
@Override
public void
Send
() {
System.out.println(
"this is sms sender!"
);
}
}
public class
SendFactory
{
public
Sender
produce
(String type) {
if
(
"mail"
.equals(type)) {
return new
MailSender();
}
else if
(
"sms"
.equals(type)) {
return new
SmsSender();
}
else
{
System.out.println(
"
请输入正确的类型
!"
);
return null
;
}
}
}
n
多个⼯⼚⽅法模式
该模式是对普通⼯⼚⽅法模式的改进,在普通⼯⼚⽅法模式中,如果传递的字符串出
错,则不能正确创建对象,⽽多个⼯⼚⽅法模式是提供多个⼯⼚⽅法,分别创建对
象。
public class
SendFactory
{
public
Sender
produceMail
() {
return new
MailSender();
}
public
Sender
produceSms
() {
return new
SmsSender();
}
}
public class
FactoryTest
{
public static void
main
(String[] args) {
SendFactory factory =
new
SendFactory();
Sender sender = factory.produceMail();
sender.send();
}
}
n
静态⼯⼚⽅法模式
将上⾯的多个⼯⼚⽅法模式⾥的⽅法置为静态的,不需要创建实例,直接调⽤即可。
public class
SendFactory
{
public static
Sender
produceMail
() {
return new
MailSender();
}
public static
Sender
produceSms
() {
return new
SmsSender();
}
}
public class
FactoryTest
{
public static void
main
(String[] args) {
Sender sender = SendFactory.produceMail();
sender.send();
}
}
n
抽象⼯⼚模式
⼯⼚⽅法模式有⼀个问题就是,类的创建依赖⼯⼚类,也就是说,如果想要拓展程
序,必须对⼯⼚类进⾏修改,这违背了闭包原则,所以,从设计⻆度考虑,有⼀定的
问题,如何解决?就⽤到抽象⼯⼚模式,创建多个⼯⼚类,这样⼀旦需要增加新的功
能,直接增加新的⼯⼚类就可以了,不需要修改之前的代码。
public interface
Provider
{
public
Sender
produce
();
}
public interface
Sender
{
public void
send
();
}
public class
MailSender
implements
Sender
{
@Override
public void
send
() {
System.out.println(
"this is mail sender!"
);
}
}
public class
SmsSender
implements
Sender
{
@Override
public void
send
() {
System.out.println(
"this is sms sender!"
);
}
}
public class
SendSmsFactory
implements
Provider
{
@Override
public
Sender
produce
() {
return new
SmsSender();
}
}
public class
SendMailFactory
implements
Provider
{
@Override
public
Sender
produce
() {
return new
MailSender();
}
}
public class
Test
{
public static void
main
(String[] args) {
Provider provider =
new
SendMailFactory();
Sender sender = provider.produce();
sender.send();
}
}
28
、建造者模式(
Builder
)
⼯⼚类模式提供的是创建单个类的模式,⽽建造者模式则是将各种产品集中起来进⾏
管理,⽤来创建复合对象, 所谓复合对象就是指某个类具有不同的属性,其实建造者
模式就是前⾯抽象⼯⼚模式和最后的
Test
结合起来得到的。
public class
Builder
{
private
List<Sender>
list
=
new
ArrayList<Sender>();
public void
produceMailSender
(
int
count) {
for
(
int
i =
0
; i < count; i++) {
list
.add(
new
MailSender());
}
}
public void
produceSmsSender
(
int
count) {
for
(
int
i =
0
; i < count; i++) {
list
.add(
new
SmsSender());
}
}
}
public class
Builder
{
private
List<Sender>
list
=
new
ArrayList<Sender>();
public void
produceMailSender
(
int
count) {
for
(
int
i =
0
; i < count; i++) {
list
.add(
new
MailSender());
}
}
public void
produceSmsSender
(
int
count) {
for
(
int
i =
0
; i < count; i++) {
list
.add(
new
SmsSender());
}
}
}
public class
TestBuilder
{
public static void
main
(String[] args) {
Builder builder =
new
Builder();
builder.produceMailSender(
10
);
}
}
29
、适配器设计模式
适配器模式将某个类的接⼝转换成客户端期望的另⼀个接⼝表示,⽬的是消除由于接
⼝不匹配所造成的类的兼容性问题。主要分为三类:类的适配器模式、对象的适配器
模式、接⼝的适配器模式。
n
类的适配器模式
public class
Source
{
public void
method1
() {
System.out.println(
"this is original method!"
);
}
}
public interface
Targetable
{
/*
与原类中的方法相同
*/
public void
method1
();
/*
新类的方法
*/
public void
method2
();
}
public class
Adapter
extends
Source
implements
Targetable
{
@Override
public void
method2
() {
System.out.println(
"this is the targetable method!"
);
}
}
public class
AdapterTest
{
public static void
main
(String[] args) {
Targetable target =
new
Adapter();
target.method1();
target.method2();
}
}
n
对象的适配器模式
基本思路和类的适配器模式相同,只是将
Adapter
类作修改,这次不继承
Source
类,⽽是持有
Source
类的实例,以达到解决兼容性的问题。
public class
Wrapper
implements
Targetable
{
private
Source source;
public
Wrapper
(Source source) {
super
();
this
.source = source;
}
@Override
public void
method2
() {
System.out.println(
"this is the targetable method!"
);
}
@Override
public void
method1
() {
source.method1();
}
}
public class
AdapterTest
{
public static void
main
(String[] args) {
Source source =
new
Source();
Targetable target =
new
Wrapper(source);
target.method1();
target.method2();
}
}
n
接⼝的适配器模式
接⼝的适配器是这样的:有时我们写的⼀个接⼝中有多个抽象⽅法,当我们写该接⼝
的实现类时,必须实现该接⼝的所有⽅法,这明显有时⽐较浪费,因为并不是所有的
⽅法都是我们需要的,有时只需要某⼀些,此处为了解决这个问题,我们引⼊了接⼝
的适配器模式,借助于⼀个抽象类,该抽象类实现了该接⼝,实现了所有的⽅法,⽽
我们不和原始的接⼝打交道,只和该抽象类取得联系,所以我们写⼀个类,继承该抽
象类,重写我们需要的⽅法就⾏。
30
、装饰模式(
Decorator
)
顾名思义,装饰模式就是给⼀个对象增加⼀些新的功能,⽽且是动态的,要求装饰对
象和被装饰对象实现同⼀个接⼝,装饰对象持有被装饰对象的实例。
public interface
Sourceable
{
public void
method
();
}
public class
Source
implements
Sourceable
{
@Override
public void
method
() {
System.out.println(
"the original method!"
);
}
}
public class
Decorator
implements
Sourceable
{
private
Sourceable source;
public
Decorator
(Sourceable source) {
super
();
this
.source = source;
}
@Override
public void
method
() {
System.out.println(
"before decorator!"
);
source.method();
System.out.println(
"after decorator!"
);
}
}
public class
DecoratorTest
{
public static void
main
(String[] args) {
Sourceable source =
new
Source();
Sourceable obj =
new
Decorator(source);
obj.method();
}
}
31
、策略模式(
strategy
)
策略模式定义了⼀系列算法,并将每个算法封装起来,使他们可以相互替换,且算法
的变化不会影响到使⽤算法的客户。需要设计⼀个接⼝,为⼀系列实现类提供统⼀的
⽅法,多个实现类实现该接⼝,设计⼀个抽象类(可有可⽆,属于辅助类),提供辅
助函数。策略模式的决定权在⽤户,系统本身提供不同算法的实现,新增或者删除算
法,对各种算法做封装。因此,策略模式多⽤在算法决策系统中,外部⽤户只需要决
定⽤哪个算法即可。
public interface
ICalculator
{
public int
calculate
(String
exp
);
}
public class
Minus
extends
AbstractCalculator
implements
ICalculator
{
@Override
public int
calculate
(String
exp
) {
int
arrayInt[] = split(
exp
,
"-"
);
return
arrayInt[
0
] - arrayInt[
1
];
}
}
public class
Plus
extends
AbstractCalculator
implements
ICalculator
{
@Override
public int
calculate
(String
exp
) {
int
arrayInt[] = split(
exp
,
"\+"
);
return
arrayInt[
0
] + arrayInt[
1
];
}
}
public class
AbstractCalculator
{
public int
[] split(String
exp
,
String opt) {
String
array
[] =
exp
.split(opt);
int
arrayInt[] =
new int
[
2
];
arrayInt[
0
] = Integer.parseInt(
array
[
0
]);
arrayInt[
1
] = Integer.parseInt(
array
[
1
]);
return
arrayInt;
}
}
public class
StrategyTest
{
public static void
main
(String[] args) {
String
exp
=
"2+8"
;
ICalculator cal =
new
Plus();
int
result = cal.calculate(
exp
);
System.out.println(result);
}
}
32
、观察者模式(
Observer
)
观察者模式很好理解,类似于邮件订阅和
RSS
订阅,当我们浏览⼀些博客或
wiki
时,
经常会看到
RSS
图标,就这的意思是,当你订阅了该⽂章,如果后续有更新,会及时
通知你。其实,简单来讲就⼀句话:当⼀个对象变化时,其它依赖该对象的对象都会
收到通知,并且随着变化!对象之间是⼀种⼀对多的关系。
public interface
Observer
{
public void
update
();
}
public class
Observer1
implements
Observer
{
@Override
public void
update
() {
System.out.println(
"observer1 has received!"
);
}
}
public class
Observer2
implements
Observer
{
@Override
public void
update
() {
System.out.println(
"observer2 has received!"
);
}
}
public interface
Subject
{
/*
增加观察者
*/
public void
add
(Observer observer);
/*
删除观察者
*/
public void
del
(Observer observer);
/*
通知所有的观察者
*/
public void
notifyObservers
();
/*
自身的操作
*/
public void
operation
();
}
public abstract class
AbstractSubject
implements
Subject
{
private
Vector<Observer> vector =
new
Vector<Observer>();
@Override
public void
add
(Observer observer) {
vector.add(observer);
}
@Override
public void
del
(Observer observer) {
vector.remove(observer);
}
@Override
public void
notifyObservers
() {
Enumeration<Observer> enumo = vector.elements();
while
(enumo.hasMoreElements()) {
enumo.nextElement().update();
}
}
}
public class
MySubject
extends
AbstractSubject
{
@Override
public void
operation
() {
System.out.println(
"update self!"
);
notifyObservers();
}
}
public class
ObserverTest
{
public static void
main
(String[] args) {
Subject sub =
new
MySubject();
sub.add(
new
Observer1());
sub.add(
new
Observer2());
sub.operation();
}
}
33
、微服务架构的六种常⽤设计模式是什么?
代理设计模式
聚合设计模式
链条设计模式
聚合链条设计模式
数据共享设计模式
异步消息设计模式
34
、设计模式是什么,设计模式有什么作⽤?
设计模式是⼀套被反复使⽤的、多数⼈知晓、经过分类编⽬的优秀代码设计经验的总
结。特定环境下特定问题的处理⽅法。
1
)重⽤设计和代码 重⽤设计⽐重⽤代码更有意义,⾃动带来代码重⽤
2
)提⾼扩展性 ⼤量使⽤⾯向接⼝编程,预留扩展插槽,新的功能或特性很容易加⼊
到系统中来
3
)提⾼灵活性 通过组合提⾼灵活性,可允许代码修改平稳发⽣,对⼀处修改不会波
及到其他模块
4
) 提⾼开发效率 正确使⽤设计模式,可以节省⼤量的时间
35
、
Spring
框架中都⽤到了哪些设计模式?
Spring
框架中使⽤到了⼤量的设计模式,下⾯列举了⽐较有代表性的:
代理模式
—
在
AOP
和
remoting
中被⽤的⽐较多。
单例模式
—
在
spring
配置⽂件中定义的
bean
默认为单例模式。
模板⽅法
—
⽤来解决代码重复的问题。⽐如
. RestTemplate, JmsTemplate, JpaTemplate
。
前端控制器
—Spring
提供了
DispatcherServlet
来对请求进⾏分发。
视图帮助
(View Helper )—Spring
提供了⼀系列的
JSP
标签,⾼效宏来辅助将分散的代码
整合在视图⾥。
依赖注⼊
—
贯穿于
BeanFactory / ApplicationContext
接⼝的核⼼理念。
⼯⼚模式
—BeanFactory
⽤来创建对象的实例