设计模式有三个分类。
创建型模式关注于对象的创建过程,强调将对象的创建与使用分离。有单例、原型、工厂方法、抽象工厂、建造者等5种创建型模式。
结构型模式则关注于如何将类或对象按照一定布局组成更大的结构。有代理、适配器、桥接、装饰、外观、享元、组合等7种结构型模式。
而行为型模式描述了类或对象之间如何协作,共同完成单个对象无法单独完成的任务,并分配职责。有模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器等11种行为型模式。
- 工厂模式
在Java中,当我们需要创建对象时,直接在代码中使用new
关键字进行实例化会导致代码的高耦合性。工厂模式可以解决这个问题。通过使用工厂来生产对象,不必关心具体对象的创建过程。如果需要更换对象,只需在工厂中进行修改即可,而无需修改代码中所有创建对象的地方。
- 模版模式
模板模式是一种行为型设计模式,它定义了算法的骨架,但将一些步骤的具体实现延迟到子类。这使得子类可以在不改变算法结构的情况下重新定义算法中的某些步骤。
抽象类(AbstractClass):定义了算法的骨架,其中包含一个模板方法,该方法定义了算法的结构,而具体步骤则由一系列抽象的操作(或称为钩子方法)组成。抽象类中可能还包含一些具体的操作,但它们通常被声明为protected,以便子类可以选择性地覆盖它们。
具体类(ConcreteClass):继承抽象类并实现抽象操作,完成算法中特定步骤的具体实现。
- 代理模式
代理模式是一种结构型设计模式,其目的是通过代理对象控制对其他对象的访问。
在代理模式中,一般会有以下几个角色:
-
抽象主题(Subject):
- 定义了真实对象和代理对象的共同接口,使得代理对象能够在任何时刻代替真实对象。
-
真实主题(Real Subject):
- 实现了抽象主题接口,是代理模式中的真实对象。它执行实际的业务逻辑。
-
代理(Proxy):
- 实现了抽象主题接口,并持有对真实对象的引用。代理对象负责在调用真实对象之前或之后执行额外的逻辑,控制对真实对象的访问。
在Java中,JDK提供了一套动态代理的机制,通过java.lang.reflect.Proxy
类和java.lang.reflect.InvocationHandler
接口来实现。以下是一个使用JDK动态代理的简单示例:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定义一个接口
interface RealObjectInterface {
void doSomething();
}
// 实际的实现类
class RealObject implements RealObjectInterface {
public void doSomething() {
System.out.println("RealObject is doing something.");
}
}
// InvocationHandler 实现
class DynamicProxyHandler implements InvocationHandler {
private Object realObject;
public DynamicProxyHandler(Object realObject) {
this.realObject = realObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在真实对象方法调用前可以添加额外逻辑
System.out.println("Before method invocation.");
// 调用真实对象的方法
Object result = method.invoke(realObject, args);
// 在真实对象方法调用后可以添加额外逻辑
System.out.println("After method invocation.");
return result;
}
}
public class DynamicProxyExample {
public static void main(String[] args) {
// 创建真实对象
RealObject realObject = new RealObject();
// 创建动态代理实例
RealObjectInterface proxyObject = (RealObjectInterface) Proxy.newProxyInstance(
RealObjectInterface.class.getClassLoader(),
new Class[]{RealObjectInterface.class},
new DynamicProxyHandler(realObject)
);
// 通过代理对象调用方法
proxyObject.doSomething();
}
}
在这个例子中,Proxy.newProxyInstance
方法会创建一个代理对象,该对象实现了指定接口(RealObjectInterface
),并使用传入的 DynamicProxyHandler
来处理方法调用。当通过代理对象调用 doSomething
方法时,实际上是调用了 DynamicProxyHandler
中的 invoke
方法,从而可以在方法调用前后添加额外逻辑。
- 适配器模式
适配器模式是一种结构型设计模式,用于将一个类的接口转换成客户端期望的另一个接口。它允许原本由于接口不匹配而无法一起工作的类能够协同工作。适配器模式通常有三个角色:目标接口(Target)、被适配者(Adaptee)、适配器(Adapter)。
以下是适配器模式的主要角色及其作用:
-
目标接口(Target):
- 客户端期望的接口,定义了客户端使用的方法。
-
被适配者(Adaptee):
- 需要被适配的接口,即客户端原本无法直接使用的类。
-
适配器(Adapter):
- 实现了目标接口,并包含一个对被适配者的引用。适配器负责将客户端的请求转发给被适配者,并在必要时进行适当的转换。
适配器模式有两种主要形式:类适配器和对象适配器。
-
类适配器:
- 使用继承来实现适配器。适配器类继承目标接口,并包含一个对被适配者的引用。这样适配器可以调用被适配者的方法,并将其转换为目标接口。
-
对象适配器:
- 使用组合来实现适配器。适配器类持有被适配者的实例,并实现目标接口。适配器通过调用被适配者的方法来实现目标接口。
- 装饰者模式
装饰者模式是一种结构型设计模式,它允许动态地给对象添加额外的职责,同时又不改变其结构。这种模式的设计目标是在不修改现有对象的情况下,通过组合方式来扩展对象的功能。
在装饰者模式中,有几个关键角色:
-
组件(Component):
- 定义一个抽象接口,用于具体组件和装饰者共同实现的接口。
-
具体组件(Concrete Component):
- 实现了组件接口,是被装饰的具体对象。
-
装饰者(Decorator):
- 持有一个指向组件对象的引用,并实现了组件的接口。装饰者通常通过委派的方式在调用组件的基础上添加额外的功能。
-
具体装饰者(Concrete Decorator):
- 扩展装饰者接口,实现具体的装饰行为。