文章目录
设计模型概念
设计模式是前人总结的软件设计经验和解决问题的最佳方案,它们为我们提供了一套可复用、易维护、可扩展的设计思路。
(1)定义: 设计模式是一套经过验证的解决特定设计问题的模板,这些模板并不是代码,而是对类、对象以及它们之间如何协作的抽象描述。
(2)目的: 降低系统的耦合性、提高代码的复用性和可维护性,以及应对不断变化的需求。
(3)设计模式主要可以分为三大类:创建型、结构型和行为型。以下是一些在 JAVA 开发工程师面试中常见的设计模式:
1. 创建型模式
- 单例模式(Singleton Pattern)
- 定义: 确保一个类只有一个实例,并提供一个全局访问点。
- 使用场景: 当系统中需要唯一一个对象来协调各部分工作,如配置管理、线程池、日志对象等。
- 工厂模式(Factory Pattern)
- 定义: 定义一个用于创建对象的接口,由子类决定实例化哪一个类。
- 使用场景: 当系统中有大量对象创建需求,且对象之间具有共同接口或父类时,可以使用工厂模式封装对象的创建逻辑,降低耦合。
- 建造者模式(Builder Pattern)
- 定义: 将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。
- 使用场景: 当一个对象的构造过程复杂,涉及多个步骤或多个可选参数时,使用建造者模式能让代码更清晰、更易扩展。
2. 结构型模式
- 适配器模式(Adapter Pattern)
- 定义: 将一个类的接口转换成客户期望的另一个接口,使得原本因接口不兼容而不能一起工作的类可以协同工作。
- 使用场景: 当你想要使用一些现有的类,但它们的接口与当前系统不匹配时,可以使用适配器模式。
- 装饰器模式(Decorator Pattern)
- 定义: 动态地给一个对象添加一些额外的职责,而不影响其他对象。
- 使用场景: 当系统需要在不改变原有对象结构的情况下增加功能时,装饰器模式提供了一种灵活的解决方案。
- 外观模式(Facade Pattern)
- 定义: 为复杂的子系统提供一个简单的接口,使得客户端可以更容易地使用子系统。
- 使用场景: 当系统中存在多个相互依赖的类或接口时,通过外观模式可以将复杂性隐藏起来,提供一个统一的接口。
3. 行为型模式
- 观察者模式(Observer Pattern)
- 定义: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,其相关依赖对象会收到通知并自动更新。
- 使用场景: 当一个对象状态的变化需要通知其他对象,且不知道这些对象的数量或具体类型时,可以使用观察者模式,如事件监听机制。
- 策略模式(Strategy Pattern)
- 定义: 定义一系列算法,把它们一个个封装起来,并使它们可以互换。
- 使用场景: 当系统中存在多种算法或行为,并且需要根据具体情况选择不同的算法时,策略模式能使算法切换更为灵活。
- 模板方法模式(Template Method Pattern)
- 定义: 在一个方法中定义一个算法的骨架,将某些步骤延迟到子类中实现,从而使子类可以不改变算法结构的情况下重新定义算法的某些步骤。
- 使用场景: 当多个子类有很多相同的行为,只在细节上略有不同的情况下,模板方法模式可以复用公共代码,同时让子类实现具体差异部分。
- 代理模式(Proxy Pattern)
- 定义: 为其他对象提供一种代理以控制对这个对象的访问。
- 使用场景: 当你需要在访问对象时附加一些额外操作(如懒加载、安全控制、缓存等)时,可以使用代理模式来控制对象的访问。
单例模式
确保一个类只有一个实例,并提供一个全局访问点。
Spring 框架中,默认 bean
的作用域为单例(singleton),即在整个应用上下文中只存在一个实例。
如 Spring 的 ApplicationContext
在加载 bean 时会确保同一个 bean 只被实例化一次(除非配置为其他作用域)。
java
public class Singleton {
// 饿汉式单例
private static volatile Singleton instance = null;
// 私有构造方法,防止外部实例化
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
sychronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
工厂模式
定义一个用于创建对象的接口,由子类决定实例化哪一个类。
Spring 的 BeanFactory
或 ApplicationContext
实际上就是一个工厂,通过配置文件或注解来实例化并管理对象。
FactoryBean
接口允许开发者自定义 bean
的创建逻辑。
java
// 定义产品接口
public interface Product {
void use();
}
// 具体产品A
public class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("使用产品A");
}
}
// 具体产品B
public class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("使用产品B");
}
}
// 工厂类
public class ProductFactory {
public static Product createProduct(String type) {
if ("A".equals(type)) {
return new ConcreteProductA();
} else if ("B".equals(type)) {
return new ConcreteProductB();
}
throw new IllegalArgumentException("未知产品类型:" + type);
}
}
// 测试入口
public class FactoryDemo {
public static void main(String[] args) {
Product productA = ProductFactory.createProduct("A");
productA.use();
Product productB = ProductFactory.createProduct("B");
productB.use();
}
}
策略模式
定义一系列算法,把它们一个个封装起来,并使它们可以互换。
当系统中有多种算法或行为需要在运行时动态切换时,可以使用策略模式。
Spring MVC 中,通过 HandlerAdapter
接口支持多种类型的控制器(如 @Controller
、@RestController
等),根据实际请求选择合适的适配器来处理业务逻辑。
事务管理、缓存策略等也采用了类似思想,通过接口和多种实现来动态选择行为。
java
// 策略接口
public interface Strategy {
void execute();
}
// 具体策略A
public class ConcreteStrategyA implements Strategy {
@Override
public void execute() {
System.out.println("执行策略A");
}
}
// 具体策略B
public class ConcreteStrategyB implements Strategy {
@Override
public void execute() {
System.out.println("执行策略B");
}
}
// 上下文,使用策略
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void executeStrategy() {
strategy.execute();
}
}
// 测试入口
public class StrategyDemo {
public static void main(String[] args) {
Context contextA = new Context(new ConcreteStrategyA());
contextA.executeStrategy();
Context contextB = new Context(new ConcreteStrategyB());
contextB.executeStrategy();
}
}
责任链模式
将请求的处理对象连成一条链,每个处理者持有对下一个处理者的引用,按顺序处理请求或将其传递给下一个处理者。
当一个请求可能由多个对象处理,但不清楚到底由哪一个对象处理时,可采用责任链模式进行动态分派。
在 Spring Security 中,FilterChainProxy
维护了一系列过滤器(Filter),每个过滤器依次处理 HTTP
请求,决定是否放行、拒绝或进一步处理。
Spring MVC 中的拦截器链(HandlerInterceptor
)也是一个责任链,每个拦截器按顺序处理请求的预处理和后处理工作。
java
// 责任链中的抽象处理者
public abstract class Handler {
protected Handler next;
// 设置下一个处理者
public void setNext(Handler next) {
this.next = next;
}
// 处理请求
public abstract void handleRequest(String request);
}
// 具体处理者A
public class ConcreteHandlerA extends Handler {
@Override
public void handleRequest(String request) {
if (request.contains("A")) {
System.out.println("ConcreteHandlerA 处理请求: " + request);
} else if (next != null) {
next.handleRequest(request);
}
}
}
// 具体处理者B
public class ConcreteHandlerB extends Handler {
@Override
public void handleRequest(String request) {
if (request.contains("B")) {
System.out.println("ConcreteHandlerB 处理请求: " + request);
} else if (next != null) {
next.handleRequest(request);
}
}
}
// 测试责任链模式
public class ChainDemo {
public static void main(String[] args) {
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
// 设置责任链顺序
handlerA.setNext(handlerB);
// 测试请求:包含 "B" 的请求由 ConcreteHandlerB 处理
handlerA.handleRequest("Request with B");
// 测试请求:包含 "A" 的请求由 ConcreteHandlerA 处理
handlerA.handleRequest("Request with A");
}
}