简介:《Java与模式》是一本深入探讨Java与设计模式结合的专业书籍,通过配套的源码实例帮助读者理解和实践各种设计模式。书中涉及多种设计模式,包括单例、工厂、观察者、装饰器、代理、建造者、适配器、桥接、组合、享元等模式,并提供Java中的实现方法。通过这些模式的应用,读者能够提升代码质量,增强项目的可读性、可维护性和复用性。
1. Java与设计模式结合概念
1.1 设计模式在Java中的重要性
在软件开发过程中,设计模式作为一种被广泛认可的解决方案,帮助开发者处理特定问题。当设计模式与Java语言结合时,可以利用Java的特性来实现这些模式,以达到增强代码复用、降低耦合、提高可维护性等目标。Java中的设计模式通常包括了创建型、结构型和行为型三大类,它们通过提供面向对象设计问题的一般解决方案,使程序设计更加规范和高效。
1.2 设计模式与Java实践的融合
在实际开发中,设计模式并不仅仅是理论知识,而是需要与具体的Java代码相结合。例如,在Java中实现单例模式,就需要利用Java的类加载机制和线程安全特性。设计模式的实践通常意味着对现有代码进行重构,以达到模式所代表的高级设计原则,如开闭原则、里氏替换原则等。
1.3 设计模式的学习路径
对于IT从业者而言,掌握设计模式有助于提高解决问题的能力。设计模式的学习应该是一个由浅入深的过程,开始时可以先从理解和实现简单的设计模式开始,比如单例模式和工厂模式。随着经验的积累,可以逐渐深入到更复杂的模式,比如代理模式、建造者模式和观察者模式等。在学习过程中,结合实际代码示例和案例分析,能更有效地掌握和应用这些设计模式。
在第一章中,我们为读者概述了设计模式与Java相结合的重要性以及学习设计模式的基本路径。下一章,我们将深入探讨单例模式在Java中的具体实现,这是理解设计模式在Java中应用的良好开端。
2. 单例模式在Java中的实现
2.1 单例模式的基本概念
2.1.1 单例模式的定义
单例模式(Singleton Pattern)是一种在设计领域中被广泛使用的设计模式。单例模式确保一个类只有一个实例,并且提供一个全局访问点来获取该实例。这个实例通常通过一个全局访问方法来创建。在Java中,实现单例模式可以保证内存中只存在一个对象实例,避免频繁的创建和销毁对象,减少系统的性能开销。
2.1.2 单例模式的特点
单例模式主要有以下特点: - 全局访问点 :提供一个全局访问点使得外界可以直接访问到这个单个实例。 - 线程安全 :单例的实现需要考虑多线程环境下的线程安全问题。 - 延迟加载 :实例的创建是在首次被请求时进行,从而避免了资源的浪费。 - 序列化和反序列化 :需要特别处理单例类对象的序列化和反序列化行为,以防止产生多个实例。
2.2 单例模式的Java实现方式
2.2.1 饿汉式实现
饿汉式单例模式的实现非常简单,它在类加载到内存后,就实例化一个对象。它的典型特点是不考虑多线程的环境,因为它在类被加载的时候就已经创建好了唯一实例。
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {}
public static EagerSingleton getInstance() {
return instance;
}
}
-
instance
:作为类的静态常量,被直接初始化,确保了实例的唯一性。 -
private
构造函数:确保了类不能通过new
关键字实例化。 -
getInstance
方法:提供全局访问点。
线程安全分析 :由于 instance
变量在类加载时就已经初始化,所以饿汉式单例在多线程环境下是线程安全的。但这种方法在类加载时就会创建实例,无论是否被使用,可能会造成内存的浪费。
2.2.2 懒汉式实现
懒汉式单例模式与饿汉式相对,它在类加载时不直接创建实例,而是在第一次被使用时才创建。
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
- 使用
synchronized
关键字确保线程安全。 -
getInstance
方法检查实例是否存在,不存在则创建。
线程安全分析 :懒汉式实现利用 synchronized
关键字保证了线程安全,但是同步方法的性能开销相对较大。尤其是在高并发的环境下,会导致性能瓶颈。
2.2.3 线程安全的单例实现
为了提高懒汉式单例在多线程环境下的性能,可以采取一些优化措施。其中一种常见的做法是双重检查锁定(Double-Checked Locking),它确保了只有在实例未被创建时才进行同步。
public class ThreadSafeLazySingleton {
private volatile static ThreadSafeLazySingleton instance;
private ThreadSafeLazySingleton() {}
public static ThreadSafeLazySingleton getInstance() {
if (instance == null) {
synchronized (ThreadSafeLazySingleton.class) {
if (instance == null) {
instance = new ThreadSafeLazySingleton();
}
}
}
return instance;
}
}
-
volatile
关键字:确保instance
变量在多线程环境下的可见性,保证了对象的正确创建。 - 双重检查锁定:降低了同步的范围,减少了同步带来的性能损失。
线程安全分析 :双重检查锁定在实例创建之前进行了两次检查,一次在同步块之外,一次在同步块之内,保证了实例的正确性和线程安全。
通过本章节的介绍,我们了解了单例模式的基本概念,以及在Java中实现单例模式的几种常见方式。每种方式都有其适用的场景和优缺点,选择合适的实现方式需要根据实际需求和环境来决定。
3. 工厂模式在Java中的实现
3.1 工厂模式的基本概念
3.1.1 工厂模式的定义
工厂模式(Factory Pattern)是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,创建对象的实例化工作被封装在一个工厂类中,这使得客户代码中不再需要直接实例化需要的对象。工厂方法让被实例化的类的客户和子类可以独立变化,而不会影响到调用者。工厂模式主要包含三种类型:简单工厂模式、工厂方法模式和抽象工厂模式。
3.1.2 工厂模式的分类
- 简单工厂模式 :通过一个工厂类创建不同产品类的实例。工厂类根据提供的参数决定创建出哪一种产品类的实例。
- 工厂方法模式 :定义了一个创建对象的抽象方法,由子类决定实例化哪一个类。工厂方法让类的实例化推迟到子类中进行。
- 抽象工厂模式 :提供一个接口用于创建相关或依赖对象的家族,而不需要明确指定具体类。抽象工厂允许系统独立于产品的创建、组合和表示变化。
3.2 工厂模式的Java实现方式
3.2.1 简单工厂模式
简单工厂模式(Simple Factory)通过一个工厂类根据传入的参数决定创建出哪一种产品类的实例。
// 产品接口
interface Product {
void use();
}
// 具体产品A
class ConcreteProductA implements Product {
public void use() {
System.out.println("Using Product A");
}
}
// 具体产品B
class ConcreteProductB implements Product {
public void use() {
System.out.println("Using Product B");
}
}
// 工厂类
class SimpleFactory {
// 制造产品的方法
public static Product createProduct(String type) {
if (type.equals("A")) {
return new ConcreteProductA();
} else if (type.equals("B")) {
return new ConcreteProductB();
}
throw new IllegalArgumentException("Unrecognized Product type");
}
}
使用时:
Product productA = SimpleFactory.createProduct("A");
productA.use();
Product productB = SimpleFactory.createProduct("B");
productB.use();
简单工厂模式适合创建产品种类较少的情况。它将创建对象的代码集中到了一个工厂类中,但缺点是扩展新产品时需要修改工厂类。
3.2.2 工厂方法模式
工厂方法模式(Factory Method)定义了一个创建对象的抽象方法,让子类决定实例化哪一个类。工厂方法把实例化操作推迟到子类。
// 创建者接口
abstract class Creator {
// 工厂方法声明
abstract Product factoryMethod();
public void someOperation() {
Product product = factoryMethod();
product.use();
}
}
// 具体创建者A
class ConcreteCreatorA extends Creator {
Product factoryMethod() {
return new ConcreteProductA();
}
}
// 具体创建者B
class ConcreteCreatorB extends Creator {
Product factoryMethod() {
return new ConcreteProductB();
}
}
使用时:
Creator creatorA = new ConcreteCreatorA();
creatorA.someOperation();
Creator creatorB = new ConcreteCreatorB();
creatorB.someOperation();
工厂方法模式适合创建产品种类较多的情况。它将具体产品的创建延迟到子类中完成,客户端仅需要知道产品的工厂类即可。
3.2.3 抽象工厂模式
抽象工厂模式(Abstract Factory)提供一个接口用于创建相关或依赖对象的家族,而不需要明确指定具体类。
// 抽象工厂
abstract class AbstractFactory {
abstract Color getColor(String color);
abstract Product getProduct(String type);
}
// 具体工厂A
class ConcreteFactoryA extends AbstractFactory {
Color getColor(String color) {
return new ConcreteColorA();
}
Product getProduct(String type) {
return new ConcreteProductA();
}
}
// 具体工厂B
class ConcreteFactoryB extends AbstractFactory {
Color getColor(String color) {
return new ConcreteColorB();
}
Product getProduct(String type) {
return new ConcreteProductB();
}
}
使用时:
AbstractFactory factoryA = new ConcreteFactoryA();
Color colorA1 = factoryA.getColor("red");
Product productA1 = factoryA.getProduct("A");
AbstractFactory factoryB = new ConcreteFactoryB();
Color colorB1 = factoryB.getColor("blue");
Product productB1 = factoryB.getProduct("B");
抽象工厂模式适合提供一系列相关或相互依赖对象的场景。它将同一产品族产品的创建封装在一起,有利于保持产品的一致性。
3.2.4 实现工厂模式的注意事项
- 何时使用工厂模式 :当创建对象需要大量重复的代码,或者产品类非常复杂,或者难以准确预知对象的创建时机时,使用工厂模式。
- 具体实现的考量 :工厂方法模式适合单一产品线;简单工厂和抽象工厂模式适合多产品线,其中抽象工厂模式较为复杂,但可以更好地应对产品族的变化。
- 扩展性 :在简单工厂模式中,如果产品种类较多,需要增加很多if或switch语句,这时候可以考虑使用工厂方法模式;工厂方法模式如果要增加产品,只需要增加一个具体的产品类和对应的工厂类即可。
- 维护性 :工厂模式可以隐藏产品的创建细节,从而可以为代码提供更好的封装性,使得客户代码与产品代码分离,降低耦合。
classDiagram
class Product {
<<interface>>
+use()
}
class ConcreteProductA {
+use()
}
class ConcreteProductB {
+use()
}
class Creator {
<<abstract>>
+factoryMethod()
+someOperation()
}
class ConcreteCreatorA {
+factoryMethod()
}
class ConcreteCreatorB {
+factoryMethod()
}
class AbstractFactory {
<<abstract>>
+getColor()
+getProduct()
}
class ConcreteFactoryA {
+getColor()
+getProduct()
}
class ConcreteFactoryB {
+getColor()
+getProduct()
}
class Color {
<<interface>>
+fill()
}
class ConcreteColorA {
+fill()
}
class ConcreteColorB {
+fill()
}
Product <|-- ConcreteProductA
Product <|-- ConcreteProductB
Creator <|-- ConcreteCreatorA
Creator <|-- ConcreteCreatorB
AbstractFactory <|-- ConcreteFactoryA
AbstractFactory <|-- ConcreteFactoryB
Product : +use()
ConcreteProductA : +use()
ConcreteProductB : +use()
Creator : +factoryMethod()
Creator : +someOperation()
ConcreteCreatorA : +factoryMethod()
ConcreteCreatorB : +factoryMethod()
AbstractFactory : +getColor()
AbstractFactory : +getProduct()
ConcreteFactoryA : +getColor()
ConcreteFactoryA : +getProduct()
ConcreteFactoryB : +getColor()
ConcreteFactoryB : +getProduct()
Color : +fill()
ConcreteColorA : +fill()
ConcreteColorB : +fill()
通过上文的介绍,我们深入了解了工厂模式的核心概念及其在Java中的实现。工厂模式通过创建抽象和封装过程,将对象的创建与使用分离,从而提升了软件的可维护性和扩展性。在接下来的章节中,我们将继续探讨Java中观察者模式、装饰器模式、代理模式等其他设计模式的实现细节。
4. 观察者模式在Java中的实现
4.1 观察者模式的基本概念
4.1.1 观察者模式的定义
观察者模式是一种行为设计模式,允许对象之间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式通常被用在事件驱动的应用中,比如GUI系统、股票分析系统和邮件通知系统等。
4.1.2 观察者模式的组成元素
观察者模式通常包含以下主要角色:
- 主题(Subject) : 定义被观察者的行为,维护一组观察者,提供注册和删除观察者的方法。
- 观察者(Observer) : 定义观察者的行为,它在主题状态改变时接收通知。
- 具体主题(ConcreteSubject) : 继承或实现主题接口,维护观察者列表,并在状态改变时通知它们。
- 具体观察者(ConcreteObserver) : 实现观察者接口,维护一个与主题状态相关的状态变量,实现更新自己的方法。
4.2 观察者模式的Java实现方式
4.2.1 使用java.util.Observable
在Java中, java.util.Observable
类和 java.util.Observer
接口提供了一种简便的方式来实现观察者模式。下面是一个使用这两个类和接口实现的例子:
import java.util.Observable;
import java.util.Observer;
public class WeatherData extends Observable {
private float temperature;
private float humidity;
public WeatherData() {}
public void setMeasurements(float temperature, float humidity) {
this.temperature = temperature;
this.humidity = humidity;
measurementsChanged();
}
private void measurementsChanged() {
setChanged();
notifyObservers();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
}
public class CurrentConditionsDisplay implements Observer {
private float temperature;
private float humidity;
private Observable weatherData;
public CurrentConditionsDisplay(Observable weatherData) {
this.weatherData = weatherData;
weatherData.addObserver(this);
}
public void update(Observable obs, Object arg) {
if (obs instanceof WeatherData) {
WeatherData weatherData = (WeatherData) obs;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();
}
}
public void display() {
System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
}
}
在这个例子中, WeatherData
类继承了 Observable
,维护了温度和湿度两个数据成员,并在状态变化时调用 measurementsChanged()
方法来通知所有注册的观察者。
CurrentConditionsDisplay
类实现了 Observer
接口,并在构造函数中注册了自身为观察者。 update()
方法会在主题状态变化时被调用,从而更新天气显示。
4.2.2 自定义观察者模式实现
虽然 java.util.Observable
和 java.util.Observer
为观察者模式提供了一个现成的实现,但它们并不总是满足所有的需求,特别是在需要对主题和观察者之间的通信进行更多控制的情况下。下面是一个自定义实现的例子:
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
public interface Observer {
void update(float temperature, float humidity);
}
public class WeatherStation implements Subject {
private List<Observer> observers = new ArrayList<>();
private float temperature;
private float humidity;
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
observers.remove(o);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature, humidity);
}
}
public void measurementsChanged() {
notifyObservers();
}
public void setMeasurements(float temperature, float humidity) {
this.temperature = temperature;
this.humidity = humidity;
measurementsChanged();
}
}
public class WeatherApp implements Observer {
private float temperature;
private float humidity;
private Subject weatherStation;
public WeatherApp(Subject weatherStation) {
this.weatherStation = weatherStation;
weatherStation.registerObserver(this);
}
@Override
public void update(float temperature, float humidity) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("WeatherApp: Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
}
}
在这个自定义实现中, Subject
和 Observer
接口提供了更加灵活的控制和扩展性。 WeatherStation
类是主题的具体实现,它通过 registerObserver()
、 removeObserver()
和 notifyObservers()
方法管理观察者。 WeatherApp
类是观察者,它实现了 Observer
接口,并在状态更新时显示信息。
4.2.3 设计模式的优点和缺点
优点:
- 解耦 : 观察者和被观察者之间是松耦合的,被观察者无需知道观察者的具体实现。
- 广播通信 : 一个被观察者的改变可以通知多个观察者。
- 异步更新 : 观察者模式支持异步处理,观察者可以在任何时候收到更新通知。
缺点:
- 性能开销 : 当观察者很多时,每次更新都会造成性能开销。
- 维护困难 : 大量的观察者和被观察者之间关系复杂,导致代码难以维护。
- 内存泄漏 : 特别是在自定义实现中,如果观察者无法被及时清除,可能会造成内存泄漏。
4.2.4 实际应用
观察者模式在软件开发中非常常见,例如在事件处理、文件系统、数据库、GUI和网络通信等领域中都有广泛的应用。例如,一个天气应用可以使用观察者模式来更新各个显示设备上的天气信息,如电视、手机应用和网页等。
4.3 观察者模式与其他模式的对比
观察者模式与发布-订阅模式非常相似,但它们之间有一个主要的区别:在发布-订阅模式中,发布者和订阅者是通过一个中间媒介进行交互的,而在观察者模式中,观察者直接订阅主题。
此外,观察者模式可以与策略模式和命令模式结合,以允许动态地更改观察者的行为。
通过在本章节中深入探讨观察者模式的实现和应用,我们已经学习了如何在Java中构建和优化这种模式。观察者模式是构建动态响应系统的强大工具,它使系统各组件之间的交互更加灵活和模块化。
5. 装饰器模式在Java中的实现
装饰器模式是一种结构型设计模式,它允许用户在不修改现有对象的结构的情况下,动态地给对象添加新的功能。与继承相比,装饰器模式提供了更为灵活的替代方案,它遵循开放/封闭原则,即软件实体应该是可扩展的,但是不可修改。
5.1 装饰器模式的基本概念
5.1.1 装饰器模式的定义
装饰器模式通过组合一个对象来扩展其行为,并保持原有对象的接口不变。装饰器类的实例将引用一个被装饰的实例,并在保持接口不变的前提下,给被装饰的类添加新的行为。
5.1.2 装饰器模式与继承的对比
继承是一种静态的、在编译时就确定下来的扩展方式,它可能导致生成许多子类,使得整个代码体系变得复杂。装饰器模式则提供了一种更为灵活的扩展方式。通过使用装饰器,可以在运行时动态地给一个对象添加额外的职责,而且可以做到只增加接口,不修改原有对象的代码。
5.2 装饰器模式的Java实现方式
5.2.1 动态代理实现装饰器模式
动态代理是Java中实现装饰器模式的一种方式,其中最常用的是JDK动态代理。在Java中,JDK动态代理需要一个实现了InvocationHandler接口的处理器来定义代理对象的行为。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DecoratorPatternDemo {
public static void main(String[] args) {
RealComponent realComponent = new RealComponent();
Component proxyInstance = (Component) Proxy.newProxyInstance(
Component.class.getClassLoader(),
new Class[]{Component.class},
new DynamicProxyHandler(realComponent));
proxyInstance.operation();
}
}
interface Component {
void operation();
}
class RealComponent implements Component {
public void operation() {
System.out.println("RealComponent operation");
}
}
class DynamicProxyHandler implements InvocationHandler {
private final Component component;
public DynamicProxyHandler(Component component) {
this.component = component;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Pre-processing before the original method execution
System.out.println("Before the method execution");
// Invoke the original method
Object result = method.invoke(component, args);
// Post-processing after the original method execution
System.out.println("After the method execution");
return result;
}
}
在这个例子中, DynamicProxyHandler
类实现了 InvocationHandler
接口,以便我们可以自定义代理对象的行为。代理对象在调用 operation
方法前后可以进行预处理和后处理操作。
5.2.2 使用装饰器模式改进IO流操作
装饰器模式也常用于Java I/O流库中。 InputStream
、 OutputStream
、 Reader
、 Writer
等抽象类都提供了装饰器模式的实现。
import java.io.*;
public class IODecoratorPatternDemo {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("input.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
int i = dis.readInt();
System.out.println("Read integer: " + i);
dis.close();
} catch (FileNotFoundException e) {
System.err.println("File not found: " + e.getMessage());
} catch (IOException e) {
System.err.println("I/O error: " + e.getMessage());
}
}
}
在上面的代码中, BufferedInputStream
和 DataInputStream
都是 InputStream
的装饰器,它们分别提供了缓冲区和数据类型的读取功能。通过组合使用这些装饰器,我们可以增强原始 FileInputStream
的能力。
Java I/O流中的装饰器模式应用非常广泛,不仅限于前面提到的几个类。通过使用装饰器模式,Java的I/O库能够提供灵活和可扩展的I/O处理能力。
装饰器模式在实际开发中非常有用,特别是当需要动态地为一个对象增加额外功能时。无论是JDK的动态代理,还是Java I/O流中的应用,都展示了装饰器模式的强大之处。通过理解并运用装饰器模式,开发者可以创建出更加灵活、可扩展的代码。
6. 代理模式在Java中的实现
代理模式是设计模式中的一种,它允许为另一个对象提供一个代理或占位符以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介的作用,并且可以根据需要来添加一些额外的功能。
6.1 代理模式的基本概念
6.1.1 代理模式的定义
代理模式涉及到三个角色: - Subject(主题接口):定义了RealSubject和Proxy的共同接口,客户端通过它来请求服务。 - RealSubject(真实主题):实现了Subject接口,实际执行操作的对象。 - Proxy(代理):持有一个RealSubject的引用,在客户端访问它时,代理可以执行一些额外的操作,例如权限检查、加载资源等,然后再将请求转发给RealSubject。
6.1.2 静态代理与动态代理
代理模式主要分为两种类型: - 静态代理:在编译期就确定了代理类的结构,并且在程序运行之前代理类的.class文件就已经存在。 - 动态代理:在程序运行期间动态地创建代理实例,根据输入参数的不同来动态生成不同的代理类。
6.2 代理模式的Java实现方式
6.2.1 静态代理的实现
在静态代理中,代理类和目标类都需要实现相同的接口。以下是简单的静态代理实现例子:
// Subject 接口
public interface Subject {
void request();
}
// RealSubject 类
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject 请求被处理");
}
}
// Proxy 类
public class ProxySubject implements Subject {
private Subject realSubject;
public ProxySubject(Subject realSubject) {
this.realSubject = realSubject;
}
@Override
public void request() {
// 额外的操作:例如权限检查
System.out.println("ProxySubject 开始处理请求");
realSubject.request();
// 额外的操作:例如资源清理
System.out.println("ProxySubject 请求处理完毕");
}
}
客户端代码:
public class Client {
public static void main(String[] args) {
Subject realSubject = new RealSubject();
Subject proxy = new ProxySubject(realSubject);
proxy.request();
}
}
6.2.2 动态代理的实现
动态代理通常使用Java的反射机制来实现。在Java中,可以通过JDK的 java.lang.reflect.Proxy
和 java.lang.reflect.InvocationHandler
接口来创建动态代理对象。
以下是动态代理实现的示例代码:
// RealSubject 类
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject 请求被处理");
}
}
// 代理的处理器
public class DynamicProxyHandler implements InvocationHandler {
private final Object target;
public DynamicProxyHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("DynamicProxyHandler 开始处理请求");
Object result = method.invoke(target, args);
System.out.println("DynamicProxyHandler 请求处理完毕");
return result;
}
}
客户端代码:
public class Client {
public static void main(String[] args) {
// 创建RealSubject实例
Subject realSubject = new RealSubject();
// 加载DynamicProxyHandler类的Class对象
InvocationHandler handler = new DynamicProxyHandler(realSubject);
// 创建动态代理对象
Subject proxy = (Subject) Proxy.newProxyInstance(
Subject.class.getClassLoader(),
new Class<?>[] {Subject.class},
handler);
proxy.request();
}
}
6.2.3 JDK动态代理与CGLIB代理的比较
JDK动态代理和CGLIB代理都是动态代理的实现,但它们有一些不同:
- JDK动态代理:要求目标对象必须实现一个接口,代理对象会去实现与目标对象相同的接口,并且每个代理方法都必须通过代理处理器
InvocationHandler
调用。 - CGLIB代理:不需要目标对象实现接口,使用类的字节码技术增强目标类,生成目标类的子类来作为代理类。
CGLIB适用于那些没有接口的类,而JDK动态代理需要基于接口。在性能上,CGLIB因为直接操作类字节码,往往比JDK动态代理略胜一筹。
本章主要介绍了代理模式在Java中的静态代理和动态代理实现方法,以及两种动态代理方式的简单比较。通过使用代理模式,可以在不改变原有对象的代码情况下,为对象添加新的功能和行为,从而达到控制访问、优化资源使用等目的。
简介:《Java与模式》是一本深入探讨Java与设计模式结合的专业书籍,通过配套的源码实例帮助读者理解和实践各种设计模式。书中涉及多种设计模式,包括单例、工厂、观察者、装饰器、代理、建造者、适配器、桥接、组合、享元等模式,并提供Java中的实现方法。通过这些模式的应用,读者能够提升代码质量,增强项目的可读性、可维护性和复用性。