单例模式(Singleton Pattern):
单例模式确保一个类只能实例化为一个对象,并提供对该对象的全局访问点。这在需要共享资源或控制独享资源的情况下非常有用。
public class Singleton {
private static Singleton instance;
private Singleton() {
// 私有构造函数
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
```
工厂模式(Factory Pattern):
工厂模式使用一个共同的接口来创建对象,但允许子类决定实例化哪个类。这样可以将对象的创建与使用代码解耦,提高了代码的可维护性和灵活性。
public interface Shape {
void draw();
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
public class ShapeFactory {
public Shape createShape(String shapeType) {
if (shapeType.equalsIgnoreCase("circle")) {
return new Circle();
} else if (shapeType.equalsIgnoreCase("rectangle")) {
return new Rectangle();
}
return null;
}
}
```
观察者模式(Observer Pattern):
观察者模式定义了一种一对多的依赖关系,使得当一个对象状态改变时,所有依赖于它的对象都会得到通知并自动更新。这在事件驱动的系统中非常有用。
import java.util.ArrayList;
import java.util.List;
public interface Observer {
void update();
}
public class Subject {
private List<Observer> observers = new ArrayList<>();
public void attach(Observer observer) {
observers.add(observer);
}
public void detach(Observer observer) {
observers.remove(observer);
}
public void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
public class ConcreteObserver implements Observer {
@Override
public void update() {
System.out.println("Received an update from the subject");
}
}
```
4,代理模式
代理模式是一种结构型设计模式,它允许通过使用代理对象来控制对另一个对象的访问。代理对象充当了客户端和被代理对象之间的中介,可以在访问被代理对象之前或之后执行一些额外的操作。
代理模式通常用于以下情况:
远程代理:代理对象充当了远程对象的本地代表,可以隐藏网络通信的复杂性,使得客户端可以像访问本地对象一样访问远程对象。
虚拟代理:代理对象用于延迟创建或加载昂贵的资源,以提高系统的性能。当真正需要资源时,代理对象才会创建或加载它们。
安全代理:代理对象用于控制对敏感对象的访问,可以验证客户端的权限或执行安全检查。
下面是一个简单的示例,演示了代理模式在 Java 中的应用:
// 接口定义了被代理对象和代理对象的共同行为
public interface Image {
void display();
}
// 实际的图像类
public class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading image from disk: " + filename);
}
@Override
public void display() {
System.out.println("Displaying image: " + filename);
}
}
// 代理类,控制对 RealImage 对象的访问
public class ImageProxy implements Image {
private String filename;
private RealImage realImage;
public ImageProxy(String filename) {
this.filename = filename;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
// 使用代理对象
public class Client {
public static void main(String[] args) {
Image image = new ImageProxy("image.jpg");
// 图像只在调用 display() 方法时才会被加载和显示
image.display();
}
}
在上面的示例中,RealImage
是实际的图像类,ImageProxy
是代理类。当调用 display()
方法时,代理对象会创建或加载真正的图像对象,并将其显示出来。这样可以实现延迟加载的效果,并且客户端只需与代理对象进行交互,无需直接访问真正的图像对象。
动态代理(Dynamic Proxy):
动态代理是一种在运行时动态生成代理对象的技术。Java 提供了 java.lang.reflect.Proxy
类和 java.lang.reflect.InvocationHandler
接口来实现动态代理。
使用动态代理,您可以在运行时为接口创建代理对象,并将方法调用重定向到实际的对象或其他处理程序。这种方式非常灵活,可以用于实现各种代理需求,例如性能监控、事务管理、日志记录等。
下面是一个简单的示例,演示了动态代理的使用:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 接口
public interface Calculator {
int add(int a, int b);
}
// 实际的实现类
public class CalculatorImpl implements Calculator {
@Override
public int add(int a, int b) {
return a + b;
}
}
// InvocationHandler 实现
public class LoggingHandler implements InvocationHandler {
private Object target;
public LoggingHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Calling method: " + method.getName());
Object result = method.invoke(target, args);
System.out.println("Method called successfully.");
return result;
}
}
// 使用动态代理
public class Client {
public static void main(String[] args) {
Calculator calculator = new CalculatorImpl();
LoggingHandler loggingHandler = new LoggingHandler(calculator);
Calculator proxy = (Calculator) Proxy.newProxyInstance(
calculator.getClass().getClassLoader(),
calculator.getClass().getInterfaces(),
loggingHandler
);
int result = proxy.add(10, 20);
System.out.println("Result: " + result);
}
}