Java设计模式总结与常见设计模式实例
发布时间: 2024-01-12 17:15:00 阅读量: 36 订阅数: 34
# 1. 导论
## 1.1 引言
在软件开发过程中,设计模式是一种反复出现的问题的解决方案。它是经过反复的使用、验证并最终被广泛接受的。设计模式不是可以直接转化为代码的,而是一种解决问题的思路。通过它可以实现代码的重用,提高代码的可读性和可维护性。
## 1.2 什么是设计模式
设计模式是在软件工程中针对特定问题的可重用解决方案。它描述了在特定环境下,可以使用的解决方案,并解释了解决方案的优缺点以及使用时机。
## 1.3 设计模式的重要性
设计模式能够提高代码的可重用性和可维护性,减少了重复劳动,增加了代码的灵活性,提高了代码的可读性以及可理解性。它们是软件工程师在工作中不可或缺的工具。
## 1.4 设计模式的分类
设计模式可以分为创建型模式、结构型模式、行为型模式和其他重要设计模式。这些分类有助于理解和学习不同类型的设计模式,以便更好地应用于实际的软件开发中。
# 2. 创建型模式
#### 2.1 简单工厂模式
##### 2.1.1 概述
简单工厂模式是指由一个工厂对象决定创建出哪一种产品类的实例。其实质是通过一个共同的接口来创建对象。该模式中定义一个创建对象的类,由这个类来封装实例化对象的代码。
##### 2.1.2 示例代码
以下是一个简单工厂模式的示例代码:
```java
// 创建产品接口
interface Product {
void show();
}
// 具体产品类A
class ConcreteProductA implements Product {
@Override
public void show() {
System.out.println("This is product A.");
}
}
// 具体产品类B
class ConcreteProductB implements Product {
@Override
public void show() {
System.out.println("This is product B.");
}
}
// 简单工厂类
class SimpleFactory {
public Product createProduct(String type) {
if ("A".equals(type)) {
return new ConcreteProductA();
} else if ("B".equals(type)) {
return new ConcreteProductB();
}
return null;
}
}
// 客户端
public class Client {
public static void main(String[] args) {
SimpleFactory factory = new SimpleFactory();
Product productA = factory.createProduct("A");
productA.show();
}
}
```
##### 2.1.3 应用场景与优缺点
**应用场景:**
- 当创建对象的逻辑较为简单,不需要太复杂的逻辑处理时
- 当客户端只需要知道所需产品对应的参数,而不关心创建细节时
**优点:**
- 封装了对象的创建过程,客户端无需关心具体的实例化逻辑
- 符合单一职责原则,将客户端和具体实现解耦
**缺点:**
- 工厂类集中了所有的产品创建逻辑,一旦需要添加新产品,就需要修改工厂类的逻辑,违反了开闭原则。
# 3. 结构型模式
#### 3.1 适配器模式
- 3.1.1 概述
适配器模式是一种结构型设计模式,它允许接口不兼容的对象能够相互合作。适配器充当两个不兼容接口之间的桥梁,将一个对象的接口转换成客户端希望的另一个接口,使得原本因接口不匹配而无法在一起工作的两个类能够协同工作。
- 3.1.2 示例代码
```java
// 目标接口
interface Target {
void request();
}
// 需要适配的类
class Adaptee {
public void specificRequest() {
System.out.println("Adaptee's specificRequest method is called.");
}
}
// 适配器
class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.specificRequest();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Adaptee adaptee = new Adaptee();
Target target = new Adapter(adaptee);
target.request();
}
}
```
- 3.1.3 应用场景与优缺点
- 应用场景:当系统需要使用现有的类,但这些类的接口不符合系统的需要时,可以使用适配器模式。比如在系统中引入一个新的接口,想要与已有的类一起工作,可以定义一个包装类来适配已有的类。
- 优点:可以让任何两个没有关联的类一起运行;增加了类的透明性和复用性;灵活性好。
- 缺点:过多地使用适配器会让系统非常零乱,不易清晰地进行整体把握。
# 4. 行为型模式
#### 4.1 策略模式
##### 4.1.1 概述
策略模式定义了一系列算法,将每个算法封装起来,并使它们可以相互替换。通常它将算法的使用和实现分离,使得算法可以在不影响客户端的情况下发生变化。
##### 4.1.2 示例代码
```python
# 策略接口
class Strategy:
def do_operation(self, num1, num2):
pass
# 具体策略类
class OperationAdd(Strategy):
def do_operation(self, num1, num2):
return num1 + num2
class OperationSubtract(Strategy):
def do_operation(self, num1, num2):
return num1 - num2
# 环境类
class Context:
def __init__(self, strategy):
self.strategy = strategy
def execute_strategy(self, num1, num2):
return self.strategy.do_operation(num1, num2)
# 使用
context = Context(OperationAdd())
print("10 + 5 =", context.execute_strategy(10, 5)) # 输出:10 + 5 = 15
context = Context(OperationSubtract())
print("10 - 5 =", context.execute_strategy(10, 5)) # 输出:10 - 5 = 5
```
##### 4.1.3 应用场景与优缺点
- **应用场景**:当一个系统需要动态地在几种算法中切换时,可使用策略模式;多个类只有算法不同的情况下,可使用策略模式。
- **优点**:
- 相互替换的算法可以独立于其使用者而变化。
- 可以减少大量的if-else语句。
- **缺点**:客户端必须知道所有的策略类,并自行决定使用哪一个策略类,增加了代码的复杂程度。
#### 4.2 观察者模式
##### 4.2.1 概述
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生变化时,会通知所有观察者对象,使它们能够自动更新。
##### 4.2.2 示例代码
```java
import java.util.ArrayList;
import java.util.List;
// 主题接口
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// 具体主题
class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private int state;
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(state);
}
}
public void setState(int state) {
this.state = state;
notifyObservers();
}
}
```
##### 4.2.3 应用场景与优缺点
- **应用场景**:当一个对象的改变需要同时改变其他对象,而且它不知道具体有多少对象有待改变时,可使用观察者模式。
- **优点**:
- 观察者和被观察者之间建立了一个抽象的耦合。
- 支持广播通信。
- **缺点**:
- 如果一个观察者与主题之间存在循环依赖,可能会导致系统崩溃。
# 5. 其他重要设计模式
#### 5.1 职责链模式
##### 5.1.1 概述
职责链模式是一种行为设计模式,用于将请求的发送者和接收者解耦,通过多个对象都有机会处理这个请求,直到其中一个对象处理它为止。这种模式可以避免请求的发送者和接收者之间的直接耦合关系。在职责链模式中,请求沿着一个对象链依次传递,直到有一个对象能够处理它为止。
##### 5.1.2 示例代码
```java
// 定义处理请求的接口
public interface Handler {
void setNext(Handler next);
void handleRequest(int request);
}
// 实现处理请求的具体类
public class ConcreteHandler1 implements Handler {
private Handler next;
public void setNext(Handler next) {
this.next = next;
}
public void handleRequest(int request) {
if (request >= 0 && request < 10) {
System.out.println("ConcreteHandler1 handled the request");
} else if (next != null) {
next.handleRequest(request);
}
}
}
public class ConcreteHandler2 implements Handler {
private Handler next;
public void setNext(Handler next) {
this.next = next;
}
public void handleRequest(int request) {
if (request >= 10 && request < 20) {
System.out.println("ConcreteHandler2 handled the request");
} else if (next != null) {
next.handleRequest(request);
}
}
}
```
##### 5.1.3 应用场景与优缺点
- **应用场景**:当请求的发送者和接收者之间需要解耦时,可以使用职责链模式。例如,一个采购单的审批流程,不同金额的采购单需要由不同级别的主管来审批。
- **优点**:职责链模式可以降低请求发送者和接收者之间的耦合;可以动态的改变处理链;符合开闭原则,可以很容易地增加或修改处理请求的类。
- **缺点**:对于某些特定的请求可能会导致请求在链条上无法被处理;如果处理链过长或者处理不当,可能会导致性能问题。
#### 5.2 状态模式
##### 5.2.1 概述
状态模式是一种行为设计模式,用于允许对象在其内部状态改变时改变它的行为。状态模式的关键思想是将对象的行为封装在不同的状态类中,对象的行为随着内部状态的改变而改变。状态模式可以使状态转换的逻辑与状态对象分离,以提高可维护性和可扩展性。
##### 5.2.2 示例代码
```python
# 定义状态接口
class State:
def do_action(self, context):
pass
# 实现状态类
class StartState(State):
def do_action(self, context):
print("Player is in start state")
context.state = self
class StopState(State):
def do_action(self, context):
print("Player is in stop state")
context.state = self
# 使用上下文来跟踪状态
class Context:
def __init__(self):
self.state = None
```
##### 5.2.3 应用场景与优缺点
- **应用场景**:当对象的行为取决于它的状态,并且在运行时可以根据状态改变行为时,可以考虑使用状态模式。例如,在一个订单状态机中,订单的状态改变会导致不同的行为。
- **优点**:状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分离开来,提高扩展性和可维护性。
- **缺点**:引入了许多小的类,增加了系统的复杂度;不适合小型的状态机。
#### 5.3 解释器模式
##### 5.3.1 概述
解释器模式是一种行为设计模式,用于定义一门语言的文法,并且利用该解释器来解释句子中的语法,即解释器模式为语言创建解释器,以解释语言中的句子。
##### 5.3.2 示例代码
```java
// 定义解释器接口
public interface Expression {
boolean interpret(String context);
}
// 实现解释器的具体类
public class TerminalExpression implements Expression {
private String data;
public TerminalExpression(String data) {
this.data = data;
}
public boolean interpret(String context) {
return context.contains(data);
}
}
public class OrExpression implements Expression {
private Expression expr1;
private Expression expr2;
public OrExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
public boolean interpret(String context) {
return expr1.interpret(context) || expr2.interpret(context);
}
}
```
##### 5.3.3 应用场景与优缺点
- **应用场景**:解释器模式适用于需要解释语言语法或执行脚本的情况。例如,SQL解释器就是一种解释器模式的典型应用。
- **优点**:易于改变和扩展文法,每条文法规则都可以通过继承一个类来进行扩展;易于实现文法,采用解释器模式可以利用面向对象技术比较容易地实现文法。
- **缺点**:对于复杂文法的解释会导致类的膨胀,增加系统的复杂性;文法的改变可能需要修改大量的源代码。
以上是第五章的内容,介绍了职责链模式、状态模式和解释器模式,包括这些模式的概述、示例代码以及应用场景与优缺点。
# 6. 总结与展望
### 6.1 设计模式的优势
设计模式的使用可以提高代码的可读性和可维护性,能够降低系统的耦合度,增加系统的灵活性和可扩展性。通过设计模式,可以让开发人员更好地理解代码结构,提高代码质量,同时也方便团队间的沟通和合作。
### 6.2 实际应用案例
设计模式在软件开发中被广泛运用,比如在Spring框架中,使用了大量的设计模式来实现各种功能。另外,在大型系统的开发中,设计模式也扮演着重要的角色,比如MVC模式在Web开发中的应用,以及各种复杂系统中的工厂模式、单例模式、观察者模式等的应用。
### 6.3 对未来的展望
随着软件开发的不断发展,设计模式也将不断演化和完善。未来,随着新技术的出现和应用场景的不断拓展,设计模式将会更加贴合实际需求,同时也会出现一些新的设计模式来解决新的问题。
### 6.4 结语
设计模式作为软件开发中的重要组成部分,对于提高代码质量、加快开发速度、降低维护成本都起到了重要作用。在实际开发中,合适地运用设计模式能够让系统更加灵活、可扩展,从而更好地适应未来的需求变化。因此,深入理解和熟练应用设计模式对于软件开发人员来说至关重要。
0
0