设计模式是软件开发过程中针对反复出现的问题所总结归纳出的通用解决方案。以下为你介绍常见的设计模式,并结合常用框架给出相应示例。
创建型模式
创建型模式主要用于对象的创建过程,封装了对象创建的细节,提高了代码的灵活性和可维护性。
单例模式(Singleton Pattern)
- 模式说明:确保一个类只有一个实例,并提供一个全局访问点。
- 框架示例:在 Spring 框架中,默认情况下,Bean 的作用域是单例的。也就是说,Spring 容器只会创建一个 Bean 实例,并且在整个应用程序中共享该实例。
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;// 定义一个单例的 Bean 类
class MySingleton {private MySingleton() {}public void doSomething() {System.out.println("Singleton is doing something.");}
}// Spring 配置类
@Configuration
class AppConfig {@Beanpublic MySingleton mySingleton() {return new MySingleton();}
}public class SingletonExample {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);MySingleton singleton1 = context.getBean(MySingleton.class);MySingleton singleton2 = context.getBean(MySingleton.class);System.out.println(singleton1 == singleton2); // 输出 true,说明是同一个实例singleton1.doSomething();}
}
工厂模式(Factory Pattern)
- 模式说明:定义一个创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。
- 框架示例:在 Java 的 JDBC 中,
DriverManager
类使用了工厂模式。DriverManager.getConnection()
方法根据不同的数据库连接信息创建不同的Connection
对象。 - BeanFactory 是 Spring 框架中最基础的工厂接口,它定义了获取 Bean 的方法,Spring 通过它来创建和管理各种 Bean 实例。BeanFactory 采用了延迟加载策略,即只有在真正需要某个 Bean 时才会去创建它。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class FactoryExample {public static void main(String[] args) {try {// 使用工厂方法获取数据库连接Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "password");System.out.println("Connected to the database.");connection.close();} catch (SQLException e) {e.printStackTrace();}}
}
结构型模式
结构型模式主要用于处理类或对象的组合,通过不同的方式将类或对象组合成更大的结构,以满足不同的需求。
代理模式(Proxy Pattern)
- 模式说明:为其他对象提供一种代理以控制对这个对象的访问。
- 框架示例:Spring AOP(面向切面编程)使用了代理模式。在 Spring AOP 中,代理对象会在目标对象的方法执行前后插入额外的逻辑,如日志记录、事务管理等。
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.NameMatchMethodPointcutAdvisor;// 目标对象接口
interface UserService {void saveUser();
}// 目标对象实现类
class UserServiceImpl implements UserService {@Overridepublic void saveUser() {System.out.println("Saving user...");}
}// 切面类
class LoggingAdvice {public void beforeAdvice() {System.out.println("Before method execution: Logging start.");}public void afterAdvice() {System.out.println("After method execution: Logging end.");}
}public class ProxyExample {public static void main(String[] args) {UserService target = new UserServiceImpl();LoggingAdvice advice = new LoggingAdvice();NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor();advisor.setMappedNames("saveUser");advisor.setAdvice(advice);ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.setTarget(target);proxyFactory.addAdvisor(advisor);UserService proxy = (UserService) proxyFactory.getProxy();proxy.saveUser();}
}
装饰器模式(Decorator Pattern)
- 模式说明:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
- 框架示例:Java 的
java.io
包中广泛使用了装饰器模式。例如,BufferedInputStream
是对InputStream
的装饰,它在InputStream
的基础上增加了缓冲功能。
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class DecoratorExample {public static void main(String[] args) {try {// 创建一个 FileInputStream 对象InputStream fileInputStream = new FileInputStream("test.txt");// 使用 BufferedInputStream 装饰 FileInputStreamInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);int data;while ((data = bufferedInputStream.read()) != -1) {System.out.print((char) data);}bufferedInputStream.close();} catch (IOException e) {e.printStackTrace();}}
}
行为型模式
行为型模式主要用于处理对象之间的交互和职责分配,关注对象之间的通信和协作。
观察者模式(Observer Pattern)
- 模式说明:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。
- 框架示例:Java 的
java.util.Observer
和java.util.Observable
类实现了观察者模式。在 Android 开发中,ListView
和Adapter
之间的关系也使用了观察者模式,当Adapter
中的数据发生变化时,ListView
会得到通知并更新显示。
import java.util.Observable;
import java.util.Observer;// 被观察的对象
class NewsAgency extends Observable {private String news;public void setNews(String news) {this.news = news;setChanged();notifyObservers(news);}
}// 观察者对象
class NewsChannel implements Observer {private String news;@Overridepublic void update(Observable o, Object arg) {this.news = (String) arg;System.out.println("Received news: " + news);}
}public class ObserverExample {public static void main(String[] args) {NewsAgency newsAgency = new NewsAgency();NewsChannel newsChannel = new NewsChannel();newsAgency.addObserver(newsChannel);newsAgency.setNews("New breaking news!");}
}
策略模式(Strategy Pattern)
- 模式说明:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。策略模式让算法的变化独立于使用算法的客户。
- 框架示例:在 Spring 框架中,
HandlerMapping
接口使用了策略模式。不同的HandlerMapping
实现类可以根据不同的策略来映射请求和处理器。
// 策略接口
interface PaymentStrategy {void pay(double amount);
}// 具体策略类:信用卡支付
class CreditCardPayment implements PaymentStrategy {@Overridepublic void pay(double amount) {System.out.println("Paying " + amount + " using credit card.");}
}// 具体策略类:支付宝支付
class AlipayPayment implements PaymentStrategy {@Overridepublic void pay(double amount) {System.out.println("Paying " + amount + " using Alipay.");}
}// 上下文类
class ShoppingCart {private PaymentStrategy paymentStrategy;public void setPaymentStrategy(PaymentStrategy paymentStrategy) {this.paymentStrategy = paymentStrategy;}public void checkout(double amount) {paymentStrategy.pay(amount);}
}public class StrategyExample {public static void main(String[] args) {ShoppingCart cart = new ShoppingCart();// 使用信用卡支付cart.setPaymentStrategy(new CreditCardPayment());cart.checkout(100.0);// 使用支付宝支付cart.setPaymentStrategy(new AlipayPayment());cart.checkout(200.0);}
}
责任链模式
模式概述
责任链模式是一种行为型设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理该请求为止。这种模式将请求的发送者和接收者解耦,使得多个对象都有机会处理请求。
常用框架举例 - Spring 的过滤器链
在 Spring 框架中,过滤器链(FilterChain
)是责任链模式的典型应用。当一个请求进入 Web 应用时,会依次经过多个过滤器,每个过滤器可以对请求进行预处理或后处理,也可以决定是否将请求传递给下一个过滤器。
以下是一个简单的自定义过滤器示例:
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;// 第一个过滤器
@WebFilter(urlPatterns = "/*")
public class FirstFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("FirstFilter: 请求预处理");chain.doFilter(request, response);System.out.println("FirstFilter: 请求后处理");}
}// 第二个过滤器
@WebFilter(urlPatterns = "/*")
public class SecondFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("SecondFilter: 请求预处理");chain.doFilter(request, response);System.out.println("SecondFilter: 请求后处理");}
}
在这个例子中,FirstFilter
和 SecondFilter
构成了一个过滤器链。当一个请求进来时,会先经过 FirstFilter
的预处理,然后传递给 SecondFilter
进行预处理,接着继续后续处理。处理完成后,会依次经过 SecondFilter
和 FirstFilter
的后处理。
模板模式
模式概述
模板模式是一种行为型设计模式,它定义了一个算法的骨架,将一些步骤的实现延迟到子类中。这样可以在不改变算法结构的情况下,让子类定制某些步骤的具体实现。
常用框架举例 - MyBatis 的 BaseExecutor
在 MyBatis 框架中,BaseExecutor
类使用了模板模式。BaseExecutor
定义了 SQL 执行的基本骨架,而具体的查询、更新等操作的实现则由其子类(如 SimpleExecutor
、ReuseExecutor
等)来完成。
以下是一个简化的 BaseExecutor
示例:
// 抽象的执行器,定义模板方法
abstract class BaseExecutor {public final void execute() {openConnection();prepareStatement();executeStatement();closeConnection();}protected abstract void openConnection();protected abstract void prepareStatement();protected abstract void executeStatement();protected abstract void closeConnection();
}// 具体的执行器实现
class SimpleExecutor extends BaseExecutor {@Overrideprotected void openConnection() {System.out.println("SimpleExecutor: 打开连接");}@Overrideprotected void prepareStatement() {System.out.println("SimpleExecutor: 准备 SQL 语句");}@Overrideprotected void executeStatement() {System.out.println("SimpleExecutor: 执行 SQL 语句");}@Overrideprotected void closeConnection() {System.out.println("SimpleExecutor: 关闭连接");}
}// 客户端代码
public class TemplatePatternExample {public static void main(String[] args) {BaseExecutor executor = new SimpleExecutor();executor.execute();}
}
在这个例子中,BaseExecutor
定义了 execute
方法作为模板方法,它包含了 SQL 执行的基本步骤。openConnection
、prepareStatement
、executeStatement
和 closeConnection
方法是抽象方法,由具体的子类 SimpleExecutor
来实现。客户端代码只需要调用 execute
方法,就可以完成整个 SQL 执行过程。