Java中常用的设计模式总览
发布时间: 2023-12-19 22:16:22 阅读量: 9 订阅数: 11
# 1. 引言
## 简介
设计模式是在软件开发过程中经验总结出的一种解决特定问题的可复用的解决方案。它们是从实践中提炼出来的,可以帮助开发者提高代码的质量、可维护性和可扩展性。
## 设计模式的作用和重要性
设计模式提供了一种通用的解决方案,可以在特定的场景中解决常见的设计问题。它们能够帮助开发者遵循一些被广泛验证的最佳实践,提高代码的可读性和可理解性。设计模式还可以促进团队合作,减少开发中的冲突和误解。通过使用设计模式,开发者可以更好地重用代码,提高开发效率,减少bug修复的工作量。
在Java中,有许多常用的设计模式,涵盖了创建型、结构型和行为型三个不同类型。本文将依次介绍这些设计模式,并通过实际的代码示例和应用场景来帮助读者更好地理解和应用设计模式。在实践中,开发者需要根据具体的情况和需求选择适合的设计模式,同时也要关注设计模式的原则和注意事项,以确保其正确的使用。通过持续学习和应用设计模式,开发者可以提高自己的设计能力和代码质量,并为软件开发打下坚实的基础。
接下来,我们将逐一介绍Java中常用的设计模式,并通过具体的例子和应用场景来帮助读者更好地理解和应用这些设计模式。
# 2. 创建型设计模式
在Java中,创建型设计模式主要用于创建对象的方式和机制。这些模式可以根据应用程序需求来选择创建对象的方式,并提供了一些标准化的解决方案。下面我们将介绍几种常用的创建型设计模式。
### 2.1 单例模式
单例模式是一种创建型设计模式,它保证一个类只有一个实例,并提供一个全局访问点来访问该实例。在Java中,我们可以使用以下方式来实现单例模式:
```java
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
```
在上面的代码中,我们使用了懒汉式的单例模式实现。当第一次调用`getInstance()`方法时,会创建一个实例,之后每次调用都会返回同一个实例。
**适用场景:**
- 当一个类只有一个实例需要被共享时。
- 当需要频繁地创建和销毁对象时,可以使用单例模式来节省资源。
**优点:**
- 提供了对唯一实例的全局访问点,方便对实例进行统一的管理。
- 减少了系统中创建对象的数量,节省了资源。
**缺点:**
- 单例模式的扩展性较差,一旦需要扩展功能,就需要修改原有的代码。
- 单例类的职责过重,既要负责创建对象,又要负责管理实例的生命周期。
### 2.2 工厂模式
工厂模式是一种创建型设计模式,它提供了一种封装对象创建过程的方式。工厂模式定义了一个用于创建对象的接口,让子类决定实例化哪一个类。在Java中,我们可以使用以下方式来实现工厂模式:
```java
public interface Product {
void doSomething();
}
public class ConcreteProduct1 implements Product {
@Override
public void doSomething() {
System.out.println("ConcreteProduct1");
}
}
public class ConcreteProduct2 implements Product {
@Override
public void doSomething() {
System.out.println("ConcreteProduct2");
}
}
public interface Factory {
Product createProduct();
}
public class ConcreteFactory1 implements Factory {
@Override
public Product createProduct() {
return new ConcreteProduct1();
}
}
public class ConcreteFactory2 implements Factory {
@Override
public Product createProduct() {
return new ConcreteProduct2();
}
}
```
上面的代码中,我们定义了一个产品接口`Product`,具体的产品类`ConcreteProduct1`和`ConcreteProduct2`实现了该接口。然后,我们定义了一个工厂接口`Factory`,具体的工厂类`ConcreteFactory1`和`ConcreteFactory2`实现了该接口,并负责创建相应的产品。
**适用场景:**
- 当一个类无法预知需要创建的对象的确切类型时。
- 当一个类希望由其子类来指定创建对象时。
**优点:**
- 隐藏了对象的创建细节,客户端只需要关心获取对象即可。
- 提供了对对象创建过程的封装,使创建对象的代码与使用对象的代码分离,降低了耦合性。
**缺点:**
- 类的个数容易增加,增加了系统的复杂度。
### 2.3 抽象工厂模式
抽象工厂模式是一种创建型设计模式,它提供了一种封装具体工厂的方式。抽象工厂模式定义了一个创建一系列相关对象的接口,让子类决定实例化哪一个类。在Java中,我们可以使用以下方式来实现抽象工厂模式:
```java
public interface ProductA {
void doSomething();
}
public class ConcreteProductA1 implements ProductA {
@Override
public void doSomething() {
System.out.println("ConcreteProductA1");
}
}
public class ConcreteProductA2 implements ProductA {
@Override
public void doSomething() {
System.out.println("ConcreteProductA2");
}
}
public interface ProductB {
void doSomething();
}
public class ConcreteProductB1 implements ProductB {
@Override
public void doSomething() {
System.out.println("ConcreteProductB1");
}
}
public class ConcreteProductB2 implements ProductB {
@Override
public void doSomething() {
System.out.println("ConcreteProductB2");
}
}
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();
}
}
```
在上面的代码中,我们定义了两个产品接口`ProductA`和`ProductB`,具体的产品类实现了这两个接口。然后,我们定义了一个抽象工厂接口`AbstractFactory`,具体的工厂类实现了该接口,并负责创建一系列相关的产品。
**适用场景:**
- 当一个类无法预知需要创建的对象的确切类型时。
- 当一个类希望由其子类来指定创建对象时。
- 当需要创建一系列相关或者相互依赖的对象时。
**优点:**
- 隐藏了对象的创建细节,客户端只需要关心获取对象即可。
- 提供了对对象创建过程的封装,使创建对象的代码与使用对象的代码分离,降低了耦合性。
- 符合开闭原则,新增具体工厂和产品都不需要修改已有的代码。
**缺点:**
- 类的个数容易增加,增加了系统的复杂度。
### 2.4 建造者模式
建造者模式是一种创建型设计模式,它将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。在Java中,我们可以使用以下方式来实现建造者模式:
```java
public class Product {
private String partA;
private String partB;
private String partC;
public String getPartA() {
return partA;
}
public void setPartA(String partA) {
this.partA = partA;
}
public String getPartB() {
return partB;
}
public void setPartB(String partB) {
this.partB = partB;
}
public String getPartC() {
return partC;
}
public void setPartC(String partC) {
this.partC = partC;
}
}
public interface Builder {
void buildPartA();
void buildPartB();
void buildPartC();
Product getResult();
}
public class ConcreteBuilder implements Builder {
private Product product;
public ConcreteBuilder() {
product = new Product();
}
@Override
public void buildPartA() {
product.setPartA("PartA");
}
@Override
public void buildPartB() {
product.setPartB("PartB");
}
@Override
public void buildPartC() {
product.setPartC("PartC");
}
@Override
public Product getResult() {
return product;
}
}
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Product construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
return builder.getResult();
}
}
```
在上面的代码中,我们定义了一个产品类`Product`,它具有多个部件。然后,我们定义了一个建造者接口`Builder`,具体的建造者类实现了该接口,并负责构建产品的各个部件。最后,我们定义了一个指挥者类`Director`,它负责控制建造过程。
**适用场景:**
- 当一个对象的构建过程比较复杂,有很多具体步骤时,可以使用建造者模式来封装构建过程。
- 当需要构建的产品有多个部件,并且构建顺序不同,或者构建过程可变时,可以使用建造者模式。
**优点:**
- 封装了对象的构建过程,使得构建过程与表示分离,可以独立地改变构建过程和表示。
- 可以更精细地控制对象的创建过程,根据不同的需要,创建不同的产品。
**缺点:**
- 建造者模式会增加代码的复杂度,因为需要定义多个类来完成对象的构建。
- 如果产品的部件之间存在关联关系,需要通过建造者类来进行处理,增加了建造者类的复杂性。
### 2.5 原型模式
原型模式是一种创建型设计模式,它通过复制一个现有对象来生成新的对象,从而避免了通过类的构造函数创建对象的过程。在Java中,我们可以使用以下方式来实现原型模式:
```java
public abstract class Prototype implements Cloneable {
public abstract Prototype clone();
}
public class ConcretePrototype extends Prototype {
private int field;
public int getField() {
return field;
}
public void setField(int field) {
this.field = field;
}
@Override
public Prototype clone() {
try {
return (Prototype) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
```
在上面的代码中,我们定义了一个抽象原型类`Prototype`,它继承了`Cloneable`接口,并实现了`clone()`方法。具体的原型类`ConcretePrototype`继承了`Prototype`类,并重写了`clone()`方法。
**适用场景:**
- 当一个对象的类型需要在运行时才能确定时,可以使用原型模式。
- 当一个对象的创建过程比较复杂,或者需要多种不同的创建方式时,可以使用原型模式。
**优点:**
- 通过复制现有对象来创建新对象,避免了通过类的构造函数创建对象的过程,提高了性能。
- 可以动态地添加或修改对象的属性。
**缺点:**
- 需要实现`Cloneable`接口和重写`clone()`方法。
- 对象的拷贝过程会涉及到对象的赋值,可能会引发深拷贝和浅拷贝的问题。
以上是创建型设计模式的一些常见模式的介绍和示例代码。通过学习和应用这些设计模式,我们可以更好地进行对象的创建和管理,提高代码的可维护性和可读性。在接下来的章节中,我们将介绍一些结构型和行为型的设计模式,敬请期待。
# 3. 结构型设计模式
结构型设计模式主要关注对象之间的组合,例如类或对象之间的组合,以提供更大的结构。
#### 1. 适配器模式
适配器模式用于将一个类的接口转换成客户希望的另外一个接口。它可以让原本由于接口不兼容而不能一起工作的类能够一起工作。
```java
// 示例:适配器模式的实现
public interface MediaPlayer {
void play(String audioType, String fileName);
}
public interface AdvancedMediaPlayer {
void playVlc(String fileName);
void playMp4(String fileName);
}
public class VlcPlayer implements AdvancedMediaPlayer {
public void playVlc(String fileName) {
System
```
0
0