Appearance
设计模式面试题
1. 设计模式的基本概念
问题:什么是设计模式?
答案:
- 设计模式:一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
- 作用:
- 提高代码的可重用性。
- 提高代码的可读性。
- 提高代码的可靠性。
- 提高代码的可维护性。
2. 设计模式的分类
问题:设计模式有哪些分类?
答案:
- 创建型模式:
- 单例模式
- 工厂方法模式
- 抽象工厂模式
- 建造者模式
- 原型模式
- 结构型模式:
- 适配器模式
- 装饰器模式
- 代理模式
- 外观模式
- 桥接模式
- 组合模式
- 享元模式
- 行为型模式:
- 策略模式
- 模板方法模式
- 观察者模式
- 迭代器模式
- 责任链模式
- 命令模式
- 备忘录模式
- 状态模式
- 访问者模式
- 中介者模式
- 解释器模式
3. 单例模式
问题:什么是单例模式?如何实现?
答案:
- 单例模式:保证一个类只有一个实例,并提供一个访问它的全局访问点。
- 实现方式:
- 饿汉式
- 懒汉式
- 双重检查锁
- 静态内部类
- 枚举
示例:
java
// 饿汉式
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
// 懒汉式
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
// 双重检查锁
public class Singleton {
private volatile static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
// 静态内部类
public class Singleton {
private Singleton() {
}
private static class Holder {
private static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return Holder.instance;
}
}
// 枚举
public enum Singleton {
INSTANCE;
public void method() {
}
}4. 工厂方法模式
问题:什么是工厂方法模式?
答案:
- 工厂方法模式:定义一个创建对象的接口,让子类决定实例化哪一个类。
- 作用:
- 解耦对象的创建和使用。
- 符合开闭原则。
示例:
java
public interface Product {
void use();
}
public class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("Product A");
}
}
public class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("Product B");
}
}
public abstract class Factory {
public abstract Product createProduct();
}
public class ConcreteFactoryA extends Factory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
public class ConcreteFactoryB extends Factory {
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}5. 抽象工厂模式
问题:什么是抽象工厂模式?
答案:
- 抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
- 作用:
- 解耦对象的创建和使用。
- 符合开闭原则。
- 支持产品族。
示例:
java
public interface ProductA {
void use();
}
public interface ProductB {
void use();
}
public class ConcreteProductA1 implements ProductA {
@Override
public void use() {
System.out.println("Product A1");
}
}
public class ConcreteProductA2 implements ProductA {
@Override
public void use() {
System.out.println("Product A2");
}
}
public class ConcreteProductB1 implements ProductB {
@Override
public void use() {
System.out.println("Product B1");
}
}
public class ConcreteProductB2 implements ProductB {
@Override
public void use() {
System.out.println("Product B2");
}
}
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
public class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
public class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}6. 建造者模式
问题:什么是建造者模式?
答案:
- 建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
- 作用:
- 解耦对象的创建和使用。
- 支持复杂对象的创建。
- 支持不同的表示。
示例:
java
public class Product {
private String partA;
private String partB;
private String partC;
public void setPartA(String partA) {
this.partA = partA;
}
public void setPartB(String partB) {
this.partB = partB;
}
public void setPartC(String partC) {
this.partC = partC;
}
@Override
public String toString() {
return "Product{" + "partA='" + partA + '\'' + ", partB='" + partB + '\'' + ", partC='" + partC + '\'' + '}';
}
}
public abstract class Builder {
public abstract void buildPartA();
public abstract void buildPartB();
public abstract void buildPartC();
public abstract Product getResult();
}
public class ConcreteBuilder extends Builder {
private Product product = new Product();
@Override
public void buildPartA() {
product.setPartA("Part A");
}
@Override
public void buildPartB() {
product.setPartB("Part B");
}
@Override
public void buildPartC() {
product.setPartC("Part C");
}
@Override
public Product getResult() {
return product;
}
}
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}
// 使用
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
director.construct();
Product product = builder.getResult();7. 原型模式
问题:什么是原型模式?
答案:
- 原型模式:通过复制现有的实例来创建新的实例,而不是通过new关键字。
- 作用:
- 提高创建对象的效率。
- 减少创建对象的资源消耗。
- 支持动态创建对象。
示例:
java
public class Prototype implements Cloneable {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
// 使用
Prototype prototype1 = new Prototype();
prototype1.setName("Prototype 1");
Prototype prototype2 = (Prototype) prototype1.clone();
prototype2.setName("Prototype 2");8. 适配器模式
问题:什么是适配器模式?
答案:
- 适配器模式:将一个类的接口转换成客户希望的另外一个接口。
- 作用:
- 解耦接口。
- 提高类的复用性。
- 符合开闭原则。
示例:
java
public interface Target {
void request();
}
public class Adaptee {
public void specificRequest() {
System.out.println("Specific request");
}
}
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.specificRequest();
}
}
// 使用
Target target = new Adapter(new Adaptee());
target.request();9. 装饰器模式
问题:什么是装饰器模式?
答案:
- 装饰器模式:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式相比生成子类更为灵活。
- 作用:
- 解耦职责。
- 支持动态添加职责。
- 符合开闭原则。
示例:
java
public interface Component {
void operation();
}
public class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("Concrete component");
}
}
public abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
public class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
System.out.println("Decorator A");
}
}
public class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
System.out.println("Decorator B");
}
}
// 使用
Component component = new ConcreteComponent();
component = new ConcreteDecoratorA(component);
component = new ConcreteDecoratorB(component);
component.operation();10. 代理模式
问题:什么是代理模式?
答案:
- 代理模式:为其他对象提供一种代理以控制对这个对象的访问。
- 作用:
- 控制对象的访问。
- 延迟加载。
- 权限控制。
示例:
java
public interface Subject {
void request();
}
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("Real subject");
}
}
public class Proxy implements Subject {
private RealSubject realSubject;
@Override
public void request() {
if (realSubject == null) {
realSubject = new RealSubject();
}
realSubject.request();
}
}
// 使用
Subject subject = new Proxy();
subject.request();11. 策略模式
问题:什么是策略模式?
答案:
- 策略模式:定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。
- 作用:
- 解耦算法和使用。
- 支持动态切换算法。
- 符合开闭原则。
示例:
java
public interface Strategy {
void execute();
}
public class ConcreteStrategyA implements Strategy {
@Override
public void execute() {
System.out.println("Strategy A");
}
}
public class ConcreteStrategyB implements Strategy {
@Override
public void execute() {
System.out.println("Strategy B");
}
}
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void execute() {
strategy.execute();
}
}
// 使用
Context context = new Context(new ConcreteStrategyA());
context.execute();12. 模板方法模式
问题:什么是模板方法模式?
答案:
- 模板方法模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
- 作用:
- 提高代码复用性。
- 支持子类扩展。
- 符合开闭原则。
示例:
java
public abstract class AbstractClass {
public void templateMethod() {
primitiveOperation1();
primitiveOperation2();
}
protected abstract void primitiveOperation1();
protected abstract void primitiveOperation2();
}
public class ConcreteClass extends AbstractClass {
@Override
protected void primitiveOperation1() {
System.out.println("Operation 1");
}
@Override
protected void primitiveOperation2() {
System.out.println("Operation 2");
}
}
// 使用
AbstractClass abstractClass = new ConcreteClass();
abstractClass.templateMethod();13. 观察者模式
问题:什么是观察者模式?
答案:
- 观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
- 作用:
- 解耦对象。
- 支持广播通信。
- 符合开闭原则。
示例:
java
public interface Observer {
void update(String message);
}
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers(String message);
}
public class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
public class ConcreteObserver implements Observer {
@Override
public void update(String message) {
System.out.println("Received: " + message);
}
}
// 使用
Subject subject = new ConcreteSubject();
Observer observer = new ConcreteObserver();
subject.registerObserver(observer);
subject.notifyObservers("Hello");14. 责任链模式
问题:什么是责任链模式?
答案:
- 责任链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
- 作用:
- 解耦请求和处理。
- 支持动态添加处理者。
- 符合开闭原则。
示例:
java
public abstract class Handler {
protected Handler next;
public Handler setNext(Handler next) {
this.next = next;
return next;
}
public abstract void handle(String request);
}
public class ConcreteHandlerA extends Handler {
@Override
public void handle(String request) {
if (request.equals("A")) {
System.out.println("Handle A");
} else if (next != null) {
next.handle(request);
}
}
}
public class ConcreteHandlerB extends Handler {
@Override
public void handle(String request) {
if (request.equals("B")) {
System.out.println("Handle B");
} else if (next != null) {
next.handle(request);
}
}
}
// 使用
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
handlerA.setNext(handlerB);
handlerA.handle("A");15. 命令模式
问题:什么是命令模式?
答案:
- 命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化。
- 作用:
- 解耦请求和执行。
- 支持撤销和重做。
- 符合开闭原则。
示例:
java
public interface Command {
void execute();
}
public class ConcreteCommand implements Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.action();
}
}
public class Receiver {
public void action() {
System.out.println("Receiver action");
}
}
public class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void execute() {
command.execute();
}
}
// 使用
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.execute();16. 状态模式
问题:什么是状态模式?
答案:
- 状态模式:允许一个对象在其内部状态改变时改变它的行为。
- 作用:
- 解耦状态和行为。
- 支持动态切换状态。
- 符合开闭原则。
示例:
java
public interface State {
void handle();
}
public class ConcreteStateA implements State {
@Override
public void handle() {
System.out.println("State A");
}
}
public class ConcreteStateB implements State {
@Override
public void handle() {
System.out.println("State B");
}
}
public class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public void handle() {
state.handle();
}
}
// 使用
Context context = new Context();
context.setState(new ConcreteStateA());
context.handle();17. 设计模式的原则
问题:设计模式有哪些原则?
答案:
- 单一职责原则:一个类只负责一项职责。
- 开闭原则:对扩展开放,对修改关闭。
- 里氏替换原则:子类可以替换父类。
- 接口隔离原则:使用多个专门的接口,而不是单一的总接口。
- 依赖倒置原则:依赖抽象而不是具体实现。
18. 设计模式的应用场景
问题:如何选择设计模式?
答案:
- 单例模式:需要唯一实例的场景。
- 工厂方法模式:需要创建对象的场景。
- 抽象工厂模式:需要创建产品族的场景。
- 建造者模式:需要创建复杂对象的场景。
- 原型模式:需要复制对象的场景。
- 适配器模式:需要接口转换的场景。
- 装饰器模式:需要动态添加职责的场景。
- 代理模式:需要控制对象访问的场景。
- 策略模式:需要切换算法的场景。
- 模板方法模式:需要定义算法骨架的场景。
- 观察者模式:需要一对多通知的场景。
- 责任链模式:需要处理请求链的场景。
- 命令模式:需要封装请求的场景。
- 状态模式:需要切换状态的场景。
19. 设计模式的优缺点
问题:设计模式有什么优缺点?
答案:
- 优点:
- 提高代码的可重用性。
- 提高代码的可读性。
- 提高代码的可靠性。
- 提高代码的可维护性。
- 缺点:
- 增加代码的复杂性。
- 增加类的数量。
- 增加系统的开销。
20. 设计模式的最佳实践
问题:使用设计模式的最佳实践有哪些?
答案:
- 根据场景选择合适的设计模式。
- 不要过度使用设计模式。
- 遵循设计模式的原则。
- 理解设计模式的意图。
- 灵活运用设计模式。
- 避免为了使用设计模式而使用设计模式。
- 保持代码的简洁性。
- 保持代码的可读性。
- 保持代码的可维护性。
- 保持代码的可扩展性。
