常见的设计模式

设计模式是面向对象设计中解决常见问题的一套最佳实践,它们为开发者提供了通用的解决方案。

1.单例模式(Singleton Pattern)

定义: 确保一个类只有一个实例,并提供一个全局访问点。
应用场景:

需要控制实例数量的类,如数据库连接池、线程池等。

需要共享的全局状态或资源的类。
实现方式:

饿汉式:在类加载时就创建实例,线程安全但可能会造成资源浪费。

懒汉式:在第一次调用时创建实例,需考虑线程安全问题。

双重检查锁定:结合懒汉式和饿汉式,确保线程安全和效率。

静态内部类:利用静态内部类实现延迟加载和线程安全。

代码示例(双重检查锁定):

java 复制代码
public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

2. 工厂模式(Factory Pattern)

定义: 提供一个创建对象的接口,而不指定具体的类。
应用场景:

需要在创建对象时进行某些配置或封装的情况。

系统需要根据不同条件创建不同对象时。
实现方式:

简单工厂:通过一个工厂类负责创建实例,根据传递的参数决定创建哪种实例。

工厂方法:将对象的创建延迟到子类中,实现类自己决定实例化哪个类。

抽象工厂:提供一个接口创建一系列相关或相互依赖的对象。

代码示例(简单工厂)

java 复制代码
public interface Product {
    void use();
}

public class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("Using Product A");
    }
}

public class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("Using Product B");
    }
}

public class Factory {
    public static Product createProduct(String type) {
        switch (type) {
            case "A":
                return new ConcreteProductA();
            case "B":
                return new ConcreteProductB();
            default:
                throw new IllegalArgumentException("Unknown product type");
        }
    }
}

// 使用
Product product = Factory.createProduct("A");
product.use();

3.策略模式(Strategy Pattern)

定义: 定义一系列算法,将每个算法封装起来,并且使它们可以互换。
应用场景:

需要在不同情况下使用不同算法,但这些算法可以替换使用。

避免使用大量条件语句选择算法的场景。
实现方式:

定义一个策略接口,各种算法实现该接口。

使用上下文类维护策略对象的引用,根据需要调用策略的方法。
代码示例:

java 复制代码
public interface Strategy {
    void execute();
}

public class ConcreteStrategyA implements Strategy {
    @Override
    public void execute() {
        System.out.println("Strategy A executed");
    }
}

public class ConcreteStrategyB implements Strategy {
    @Override
    public void execute() {
        System.out.println("Strategy B executed");
    }
}

public class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void executeStrategy() {
        strategy.execute();
    }
}

// 使用
Context context = new Context(new ConcreteStrategyA());
context.executeStrategy();

4.观察者模式(Observer Pattern)

定义: 定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,其依赖者会收到通知并自动更新。
应用场景:

一个对象的改变需要通知其他对象,而这些对象不需要强耦合。

事件监听机制的实现,如GUI框架中的事件处理。
实现方式:

被观察者维护一组观察者列表,当状态变化时,遍历通知所有观察者。
代码示例:

java 复制代码
import java.util.ArrayList;
import java.util.List;

public interface Observer {
    void update();
}

public class ConcreteObserver implements Observer {
    @Override
    public void update() {
        System.out.println("Observer notified");
    }
}

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 void changeState() {
        // 状态改变逻辑
        notifyObservers();
    }
}

// 使用
Subject subject = new Subject();
Observer observer = new ConcreteObserver();
subject.attach(observer);
subject.changeState();

5.代理模式(Proxy Pattern)

定义: 为其他对象提供一种代理,以控制对这个对象的访问。
应用场景:

需要在访问对象前后添加额外操作、如权限控制、缓存、日志等。

远程代理控制对远程对象的访问。
实现方式:

静态代理:通过在编译时创建代理类来控制访问。

动态代理:在运行时动态生成代理类,可以拦截方法调用。
代码示例(动态代理)

java 复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public interface Service {
    void perform();
}

public class RealService implements Service {
    @Override
    public void perform() {
        System.out.println("Performing real service");
    }
}

public class ServiceProxy implements InvocationHandler {
    private Object target;

    public ServiceProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before invoking real service");
        Object result = method.invoke(target, args);
        System.out.println("After invoking real service");
        return result;
    }

    public static Service createProxy(Service target) {
        return (Service) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new ServiceProxy(target)
        );
    }
}

// 使用
Service service = new RealService();
Service proxyService = ServiceProxy.createProxy(service);
proxyService.perform();

6.装饰者模式(Decorator Pattern)

定义: 动态地给对象添加一些额外的职责,就增加功能来说,装饰模式相比生成子类更为灵活。
应用场景

需要在不修改原类的情况下动态地给一个对象添加额外的功能。

需要扩展对象功能,且可能动态组合这些功能
实现方式:

装饰者和被装饰的类实现同一个接口。

在装饰者中持有被装饰对象的引用,并在方法中调用被装饰对象的方法,同时添加自己的逻辑。
代码示例:

java 复制代码
public interface Component {
    void operation();
}

public class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("Executing operation");
    }
}

public class Decorator implements Component {
    private Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        System.out.println("Decorator before operation");
        component.operation();
        System.out.println("Decorator after operation");
    }
}

// 使用
Component component = new ConcreteComponent();
Component decorator = new Decorator(component);
decorator.operation();

7.责任链模式

责任链模式(Chain of Responsibility Pattern) 是一种行为设计模式,它允许将请求沿着处理链传递,直到有一个对象处理该请求为止。这种模式使多个对象都有机会处理请求,从而避免了请求的发送者与接收者之间的耦合。

应用场景:

需要动态地决定由哪个对象来处理请求的场景。

需要在不明确接收者的情况下,向多个对象中的一个提交请求。

需要将请求的处理逻辑与请求的发送者解耦时。

优点

降低耦合度:请求者和处理者解耦,请求者不需要知道哪个处理者会最终处理请求。

动态组合处理对象:可以在运行时动态地改变链中的处理者或调整顺序。

扩展灵活性:增加新的处理者类时,无需修改原有代码,符合开闭原则。

缺点

可能未处理请求:如果链过长或没有合理的终止条件,可能会导致请求未被处理。

调试困难:由于请求是在链上传递的,可能难以追踪请求的处理路径。

实现方式

在实现责任链模式时,通常有以下几个核心组件:

抽象处理者(Handler):定义处理请求的接口,并持有下一个处理者的引用。

具体处理者(ConcreteHandler):继承抽象处理者,实现处理请求的逻辑。

客户端(Client):创建责任链,并将请求传递给责任链的第一个处理者。

代码示例

java 复制代码
// 抽象处理者类
abstract class Handler {
    protected Handler nextHandler;

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public void handleRequest(int request) {
        if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}

// 具体处理者类A
class ConcreteHandlerA extends Handler {
    @Override
    public void handleRequest(int request) {
        if (request < 10) {
            System.out.println("ConcreteHandlerA handled request " + request);
        } else {
            super.handleRequest(request);
        }
    }
}

// 具体处理者类B
class ConcreteHandlerB extends Handler {
    @Override
    public void handleRequest(int request) {
        if (request >= 10 && request < 20) {
            System.out.println("ConcreteHandlerB handled request " + request);
        } else {
            super.handleRequest(request);
        }
    }
}

// 具体处理者类C
class ConcreteHandlerC extends Handler {
    @Override
    public void handleRequest(int request) {
        if (request >= 20) {
            System.out.println("ConcreteHandlerC handled request " + request);
        } else {
            super.handleRequest(request);
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 创建处理者对象
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        Handler handlerC = new ConcreteHandlerC();

        // 组装责任链
        handlerA.setNextHandler(handlerB);
        handlerB.setNextHandler(handlerC);

        // 提交请求
        int[] requests = {3, 14, 22, 7, 18};
        for (int request : requests) {
            handlerA.handleRequest(request);
        }
    }
}

运行结果

在上述代码中,客户端创建了三个处理者 ConcreteHandlerAConcreteHandlerBConcreteHandlerC,并将它们链接起来形成责任链。每个处理者根据请求的值决定是否处理请求,或者将请求传递给下一个处理者。运行结果如下:

java 复制代码
ConcreteHandlerA handled request 3
ConcreteHandlerB handled request 14
ConcreteHandlerC handled request 22
ConcreteHandlerA handled request 7
ConcreteHandlerB handled request 18
相关推荐
哪 吒4 小时前
最简单的设计模式,抽象工厂模式,是否属于过度设计?
设计模式·抽象工厂模式
Theodore_10224 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
冰帝海岸5 小时前
01-spring security认证笔记
java·笔记·spring
世间万物皆对象5 小时前
Spring Boot核心概念:日志管理
java·spring boot·单元测试
没书读了6 小时前
ssm框架-spring-spring声明式事务
java·数据库·spring
小二·6 小时前
java基础面试题笔记(基础篇)
java·笔记·python
开心工作室_kaic6 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
懒洋洋大魔王6 小时前
RocketMQ的使⽤
java·rocketmq·java-rocketmq
武子康6 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
转世成为计算机大神7 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式