Java设计模式业务场景及简单代码示例

317 阅读18分钟

Java中一共有23种设计模式,这些设计模式分为三类:创建型、结构型和行为型。以下是Java中所有的设计模式:

创建型模式

  1. 简单工厂模式(Simple Factory Pattern)
  2. 工厂方法模式(Factory Method Pattern)
  3. 抽象工厂模式(Abstract Factory Pattern)
  4. 单例模式(Singleton Pattern)
  5. 原型模式(Prototype Pattern)
  6. 建造者模式(Builder Pattern)

结构型模式

  1. 适配器模式(Adapter Pattern)
  2. 桥接模式(Bridge Pattern)
  3. 组合模式(Composite Pattern)
  4. 装饰器模式(Decorator Pattern)
  5. 外观模式(Facade Pattern)
  6. 享元模式(Flyweight Pattern)
  7. 代理模式(Proxy Pattern)

行为型模式

  1. 职责链模式(Chain of Responsibility Pattern)
  2. 命令模式(Command Pattern)
  3. 解释器模式(Interpreter Pattern)
  4. 迭代器模式(Iterator Pattern)
  5. 中介者模式(Mediator Pattern)
  6. 备忘录模式(Memento Pattern)
  7. 观察者模式(Observer Pattern)
  8. 状态模式(State Pattern)
  9. 策略模式(Strategy Pattern)
  10. 模板方法模式(Template Method Pattern)
  11. 访问者模式(Visitor Pattern)

以上所有的设计模式都有各自的应用场景,可以提高代码的可复用性、可维护性和可扩展性,同时也能使代码更加清晰易懂。在实际开发中,根据具体的业务场景和需求,选择合适的设计模式来解决问题,能够提高开发效率和开发质量。

单例模式

业务场景:在 Java 中,适用于单例模式的场景通常是需要确保某个类只有一个实例,并且这个实例需要被全局访问的情况。比如,线程池、配置管理、数据库连接,或是需要共享某些资源的情况下。通过单例模式,能够确保这些类只有一个实例,避免多个实例创建和资源浪费,提高系统的性能和健壮性。

下面是一个单例模式的示例代码,其中我们使用了懒汉式的实现方式,即只有在第一次使用的时候才创建实例。具体实现如下:

public class Singleton {
    // 1. 私有静态变量,使用volatile关键字确保线程安全
    private static volatile Singleton instance;
    
    // 2. 私有构造方法,防止外部实例化
    private Singleton() {
        // do something
    }
    
    // 3. 全局访问点,获取实例
    public static Singleton getInstance() {
        // 4. 双重检查锁,确保线程安全,并且只有在第一次使用时才创建实例
        if(instance == null) {
            synchronized (Singleton.class) {
                if(instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
    
    // 其他业务方法
    public void doSomething() {
        // do something
    }
}

在该示例代码中,我们使用了私有静态变量 instance 来存储实例,使用 volatile 关键字确保其在线程间的可见性,防止多线程情况下出现空指针等问题。私有构造方法防止外部实例化,全局访问点确保了唯一的实例,双重检查锁确保了线程安全。其他业务方法可以根据具体需求进行添加。

工厂方法模式

业务场景:比如在电商项目中,适合使用工厂方法模式的场景有很多:

  1. 商品的创建:在电商平台上,可能有很多不同类型的商品,如服装、数码产品、家居用品等,每个商品都有自己的属性和特点。使用工厂方法模式,能够根据商品类型动态创建不同类型的商品实例,提高代码复用性和可拓展性。例如:
public abstract class Product {
    // ... 省略其他属性和方法
}

public class ClothingProduct extends Product {
    // ... 省略特有属性和方法
}

public class DigitalProduct extends Product {
    // ... 省略特有属性和方法
}

public class ProductFactory {
    public static Product create(int category, String name, double price, String... args) {
        if(category == 1) {
            // 创建服装商品
            return new ClothingProduct(name, price, args);
        } else if(category == 2) {
            // 创建数码商品
            return new DigitalProduct(name, price, args);
        } else {
            // 不支持的商品类别
            return null;
        }
    }
}

2. 订单的处理:在电商平台上,订单是非常重要的一环,每个订单都包含了购买者、商品、价格等重要信息。使用工厂方法模式,能够根据不同的订单类型(如普通订单、团购订单、秒杀订单等)动态创建不同类型的订单实例。例如:

public abstract class Order {
    // ... 省略其他属性和方法
}

public class NormalOrder extends Order {
    // ... 省略特有属性和方法
}

public class GroupOrder extends Order {
    // ... 省略特有属性和方法
}

public class SecKillOrder extends Order {
    // ... 省略特有属性和方法
}

public class OrderFactory {
    public static Order create(int type, User user, Product product, double price, String... args) {
        if(type == 1) {
            // 创建普通订单
            return new NormalOrder(user, product, price, args);
        } else if(type == 2) {
            // 创建团购订单
            return new GroupOrder(user, product, price, args);
        } else if(type == 3) {
            // 创建秒杀订单
            return new SecKillOrder(user, product, price, args);
        } else {
            // 不支持的订单类型
            return null;
        }
    }
}

3. 折扣的计算:在电商平台上,经常会出现折扣活动。使用工厂方法模式,能够根据不同的活动类型(如满减、打折、Coupon等)动态创建不同类型的折扣计算实例。例如:

public interface Discount {
    // 计算折扣后的价格
    double calculate(double originPrice, String... args);
}

public class FullReductionDiscount implements Discount {
    // ... 省略实现
}

public class DiscountDiscount implements Discount {
    // ... 省略实现
}

public class CouponDiscount implements Discount {
    // ... 省略实现
}

public class DiscountFactory {
    public static Discount create(int type, String... args) {
        if(type == 1) {
            // 创建满减计算器
            return new FullReductionDiscount(...);
        } else if(type == 2) {
            // 创建打折计算器
            return new DiscountDiscount(...);
        } else if(type == 3) {
            // 创建Coupon计算器
            return new CouponDiscount(...);
        } else {
            // 不支持的折扣类型
            return null;
        }
    }
}

以上是在电商项目中使用工厂方法模式的一些场景和示例代码。通过工厂方法模式,我们能够将系统中的对象创建和管理与其它业务逻辑解耦,提高了系统的可扩展性和可维护性。

策略模式

策略模式适用于需要在运行时根据不同的情况选择不同的算法或策略的场景,在实际业务中,可以使用策略模式来封装一些算法、逻辑、业务规则等,达到解耦、扩展和维护的效果。

下面是一些适合使用策略模式的场景:

  1. 计算器:在一个系统中可能有很多的计算器,如加法计算器、减法计算器、乘法计算器、除法计算器等,这些计算器共用了相同的接口,称之为“计算器策略”。使用策略模式,能够动态地切换不同类型的计算器策略。例如:
public interface CalculatorStrategy {
    double calculate(double num1, double num2);
}

public class AddStrategy implements CalculatorStrategy {
    @Override
    public double calculate(double num1, double num2) {
        return num1 + num2;
    }
}

public class SubStrategy implements CalculatorStrategy {
    @Override
    public double calculate(double num1, double num2) {
        return num1 - num2;
    }
}

public class MulStrategy implements CalculatorStrategy {
    @Override
    public double calculate(double num1, double num2) {
        return num1 * num2;
    }
}

public class DivStrategy implements CalculatorStrategy {
    @Override
    public double calculate(double num1, double num2) {
        if(num2 == 0) {
            throw new IllegalArgumentException("除数不能为0");
        }
        return num1 / num2;
    }
}

public class Calculator {
    // 计算器策略
    private CalculatorStrategy strategy;
    
    // 构造函数
    public Calculator(CalculatorStrategy strategy) {
        this.strategy = strategy;
    }
    
    // 调用计算器策略计算结果
    public double getResult(double num1, double num2) {
        return strategy.calculate(num1, num2);
    }
}

2. 支付方式:在电商平台上,可能有很多不同的支付方式,如支付宝、微信、银行卡等,这些支付方式共用了相同的接口,称之为“支付策略”。使用策略模式,能够动态地切换支付策略。例如:

public interface PaymentStrategy {
    boolean pay(double amount);
}

public class AlipayStrategy implements PaymentStrategy {
    @Override
    public boolean pay(double amount) {
        // 调用支付宝支付接口
        return true;
    }
}

public class WechatPayStrategy implements PaymentStrategy {
    @Override
    public boolean pay(double amount) {
        // 调用微信支付接口
        return true;
    }
}

public class BankCardStrategy implements PaymentStrategy {
    @Override
    public boolean pay(double amount) {
        // 调用银行卡支付接口
        return true;
    }
}

public class Payment {
    // 支付策略
    private PaymentStrategy strategy;
    
    // 构造函数
    public Payment(PaymentStrategy strategy) {
        this.strategy = strategy;
    }
    
    // 调用支付策略完成支付
    public boolean pay(double amount) {
        return strategy.pay(amount);
    }
}

3. 奖励分发:在奖励分发系统中,可能根据不同的业务规则(如活动规则、用户等级等)实现不同的分发策略。通过使用策略模式,能够灵活地调整奖励分发策略。例如:

public interface RewardStrategy {
    void reward(User user, double amount);
}

public class ActivityRewardStrategy implements RewardStrategy {
    @Override
    public void reward(User user, double amount) {
        // 活动奖励规则
    }
}

public class LevelRewardStrategy implements RewardStrategy {
    @Override
    public void reward(User user, double amount) {
        // 用户等级奖励规则
    }
}

public class RewardDispatcher {
    // 奖励分发策略
    private RewardStrategy strategy;
    
    // 构造函数
    public RewardDispatcher(RewardStrategy strategy) {
        this.strategy = strategy;
    }
    
    // 调用奖励分发策略完成奖励分发
    public void dispatch(User user, double amount) {
        strategy.reward(user, amount);
    }
}

4:电商满减

比如满1000减100,2000 减 200,3000 减300这种业务场景可以使用策略模式来实现,以下是示例代码:

DiscountStrategy.java

public interface DiscountStrategy {
    double getDiscount(double amount);
}

FixedDiscountStrategy.java

public class FixedDiscountStrategy implements DiscountStrategy {
    private double discountAmount;

    public FixedDiscountStrategy(double discountAmount) {
        this.discountAmount = discountAmount;
    }

    @Override
    public double getDiscount(double amount) {
        return discountAmount;
    }
}

RangeDiscountStrategy.java

public class RangeDiscountStrategy implements DiscountStrategy {
    private double rangeAmount;
    private double discountAmount;

    public RangeDiscountStrategy(double rangeAmount, double discountAmount) {
        this.rangeAmount = rangeAmount;
        this.discountAmount = discountAmount;
    }

    @Override
    public double getDiscount(double amount) {
        if (amount >= rangeAmount) {
            return discountAmount;
        }
        return 0;
    }
}

DiscountContext.java

public class DiscountContext {
    private DiscountStrategy strategy;

    public DiscountContext(DiscountStrategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(DiscountStrategy strategy) {
        this.strategy = strategy;
    }

    public double discount(double amount) {
        return amount - strategy.getDiscount(amount);
    }
}

使用时,可以在客户端代码中进行实例化和设置不同的策略:

public class Client {
    public static void main(String[] args) {
        DiscountContext context = new DiscountContext(new FixedDiscountStrategy(0));
        double amount = 2000;
        if (amount >= 1000 && amount < 2000) {
            context.setStrategy(new FixedDiscountStrategy(100));
        } else if (amount >= 2000 && amount < 3000) {
            context.setStrategy(new FixedDiscountStrategy(200));
        } else if (amount >= 3000) {
            context.setStrategy(new FixedDiscountStrategy(300));
        }
        double discountedAmount = context.discount(amount);
        System.out.println("原价:" + amount + ",折后价:" + discountedAmount);
    }
}

在这个示例中,构造函数可以接受不同的参数来设置策略,实现了手动控制减免金额的功能,而客户端代码在不修改核心代码的情况下,可以根据不同的条件动态地设置不同的策略。 以上是在实际业务中使用策略模式的一些场景和示例代码。通过策略模式,我们能够将算法和业务逻辑从上层的调用程序中隔离出来,提高代码的可维护性和可扩展性,并能够动态地切换不同类型的算法和业务逻辑实现。

观察者模式

观察者模式适用于具有一对多关系的场景,当一个对象的状态发生改变时,需要通知多个观察者对象进行相应操作。在实际业务中,观察者模式常用于事件处理、消息推送、状态监测等场景。

以下是一些适合使用观察者模式的业务场景:

  1. 警报系统:警报系统需要在某些事件发生时(如火警、洪水等),通知到多个接收者(如警察、消防队等),这种情况下比较适合使用观察者模式。例如:
public interface AlarmListener {
    void onAlarm(AlarmEvent event);
}

public class FireAlarm {
    private List<AlarmListener> listeners = new ArrayList<>();

    // 添加观察者
    public void addListener(AlarmListener listener) {
        this.listeners.add(listener);
    }

    // 移除观察者
    public void removeListener(AlarmListener listener) {
        this.listeners.remove(listener);
    }

    // 触发事件
    public void onFire() {
        AlarmEvent event = new AlarmEvent("火警");
        for(AlarmListener listener : listeners) {
            listener.onAlarm(event);
        }
    }
}

2. 消息订阅:在一个消息订阅系统中,可能有很多订阅者,需要订阅特定的消息类型,并在消息到达时收到通知。这种情况下比较适合使用观察者模式。例如:

public interface MessageListener {
    void onMessage(MessageEvent event);
}

public class MessageBroker {
    private Map<String, List<MessageListener>> listeners = new HashMap<>();

    // 添加观察者
    public void addListener(String topic, MessageListener listener) {
        List<MessageListener> list = listeners.getOrDefault(topic, new ArrayList<>());
        list.add(listener);
        listeners.put(topic, list);
    }

    // 移除观察者
    public void removeListener(String topic, MessageListener listener) {
        List<MessageListener> list = listeners.getOrDefault(topic, new ArrayList<>());
        list.remove(listener);
        listeners.put(topic, list);
    }

    // 发布消息
    public void publish(String topic, String message) {
        MessageEvent event = new MessageEvent(topic, message);
        List<MessageListener> list = listeners.getOrDefault(topic, new ArrayList<>());
        for(MessageListener listener : list) {
            listener.onMessage(event);
        }
    }
}

3. 用户注册:在用户注册流程中,可能需要多个步骤,如用户账号的创建、信息的完善、邮件的发送等,这些步骤需要在用户完成之后才能进行。使用观察者模式,可以将每个步骤看作一个观察者,并在用户注册完成后通知所有的观察者。例如:

public interface UserObserver {
    void onAccountCreated(User user);
    void onInfoComplete(User user);
    void onMailSent(User user);
}

public class UserService {
    private List<UserObserver> observers = new ArrayList<>();

    // 添加观察者
    public void addObserver(UserObserver observer) {
        this.observers.add(observer);
    }

    // 移除观察者
    public void removeObserver(UserObserver observer) {
        this.observers.remove(observer);
    }

    // 用户注册流程
    public void register(User user) {
        UserDAO.createAccount(user);
        for(UserObserver observer : observers) {
            observer.onAccountCreated(user);
        }
        UserDAO.completeInfo(user);
        for(UserObserver observer : observers) {
            observer.onInfoComplete(user);
        }
        EmailService.sendMail(user.getEmail());
        for(UserObserver observer : observers) {
            observer.onMailSent(user);
        }
    }
}

以上是在实际业务中使用观察者模式的一些场景和示例代码。观察者模式能够实现对象之间的解耦,一个对象的变化不会影响到其他对象。通过使用观察者模式,能够更加方便地添加或删除观察者,也能够动态地扩展系统的功能和逻辑。

监听器模式

监听器模式是一种基于事件的设计模式,适用于事件通知和响应的场景,常用于GUI开发、网络编程、多线程等复杂应用环境中。在Java中,监听器模式可以通过接口回调实现,开发者可以自定义事件和监听器实现自己的业务逻辑。

以下是几个适用于监听器模式的业务场景和示例代码:

  1. GUI开发:在Java中,Swing等图形化界面开发工具包使用了大量的监听器模式,例如,鼠标点击、键盘按下等事件都是通过监听器实现。例如:
public interface MouseClickListener {
    void onClick(MouseEvent event);
}

public class MyButton {
    private List<MouseClickListener> listeners = new ArrayList<>();

    public void addClickListener(MouseClickListener listener) {
        this.listeners.add(listener);
    }

    public void removeClickListener(MouseClickListener listener) {
        this.listeners.remove(listener);
    }

    // 当鼠标单击事件发生时,触发所有的监听器
    private void onMouseClick(MouseEvent event) {
        for(MouseClickListener listener : listeners) {
            listener.onClick(event);
        }
    }
}
  1. 网络编程:网络编程中,常常需要监听端口,接收来自客户端的请求,并回调业务逻辑代码。例如:
public interface ConnectionListener {
    void onConnection(ConnectionEvent event);
}

public class Server {
    private List<ConnectionListener> listeners = new ArrayList<>();

    public void start(int port) {
        // 监听端口,接收来自客户端的请求
        // ...
        // 当有客户端连接时,触发所有的监听器
        ConnectionEvent event = new ConnectionEvent(socket);
        for(ConnectionListener listener : listeners) {
            listener.onConnection(event);
        }
    }

    public void addListener(ConnectionListener listener) {
        this.listeners.add(listener);
    }

    public void removeListener(ConnectionListener listener) {
        this.listeners.remove(listener);
    }
}
  1. 多线程:在Java中,多线程中的线程池等机制,也可以使用监听器模式来实现任务的提交和回调。例如:
public interface TaskListener {
    void onTaskComplete(TaskEvent event);
}

public class ThreadPool {
    private Executor executor = Executors.newFixedThreadPool(10);
    private List<TaskListener> listeners = new ArrayList<>();

    public void submit(Runnable task) {
        executor.execute(() -> {
            task.run();
            // 任务完成后,触发所有的监听器
            TaskEvent event = new TaskEvent(task);
            for(TaskListener listener : listeners) {
                listener.onTaskComplete(event);
            }
        });
    }

    public void addListener(TaskListener listener) {
        this.listeners.add(listener);
    }

    public void removeListener(TaskListener listener) {
        this.listeners.remove(listener);
    }
}

在以上示例中,我们定义了三个接口,分别是 MouseClickListener(鼠标单击事件监听器)、ConnectionListener(连接事件监听器)和 TaskListener(任务完成事件监听器)。其中,每个接口都定义了回调方法,当对应的事件发生时,触发所有的监听器。

然后,我们实现了具体的业务类(如 MyButtonServerThreadPool),在这些类中,都实现了添加、移除监听器方法以及触发事件方法。

装饰器模式

装饰器模式是一种结构型设计模式,可以通过装饰器来动态地给对象添加功能。在Java中,装饰器模式可以通过继承或者实现同一个接口来实现,这种方式可以让我们在不改变原有代码的基础上,对对象进行功能增强和扩展。类似于AOP。

以下是几个适用于装饰器模式的业务场景和示例代码:

  1. 日志记录:在Java应用程序中,常常需要记录日志。我们可以使用装饰器模式,在日志输出前后添加时间戳、线程号等信息。例如:
public interface Logger {
    void log(String message);
}

public class SimpleLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println(message);
    }
}

public class TimestampLogger implements Logger {
    private Logger logger;

    public TimestampLogger(Logger logger) {
        this.logger = logger;
    }

    @Override
    public void log(String message) {
        String logMessage = System.currentTimeMillis() + " " + message;
        logger.log(logMessage);
    }
}

public class ThreadLogger implements Logger {
    private Logger logger;

    public ThreadLogger(Logger logger) {
        this.logger = logger;
    }

    @Override
    public void log(String message) {
        String logMessage = Thread.currentThread().getName() + " " + message;
        logger.log(logMessage);
    }
}

在以上示例中,我们定义了一个Logger接口,一个SimpleLogger实现类和两个装饰器类(TimestampLogger和ThreadLogger)。其中装饰器类均实现了Logger接口,并在调用log方法前后添加了不同的信息,依次实现了增强功能的实现。

  1. 输入输出流的处理:在Java IO中,我们可以使用装饰器模式对输入输出流进行处理,例如:
InputStream in = new FileInputStream("example.txt");
in = new GZIPInputStream(in);
in = new BufferedInputStream(in);

在以上示例中,我们使用了多层装饰器来处理输入流。首先通过文件输入流(FileInputStream)来读取文件,然后添加压缩(GZIPInputStream)和缓冲(BufferedInputStream)装饰器对输入流进行增强,最终返回一个流处理器(InputStream)。

  1. 缓存处理:在Java中,我们可以使用装饰器来实现缓存处理,例如:
public interface DataSource {
    String getData();
}

public class DBDataSource implements DataSource {
    @Override
    public String getData() {
        // 从数据库读取数据
        return null;
    }
}

public class CacheDataSource implements DataSource {
    private DataSource dataSource;
    private String data;

    public CacheDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public String getData() {
        if (data == null) {
            data = dataSource.getData();
        }
        return data;
    }
}

在以上示例中,我们定义了一个DataSource接口,有一个实现类DbDataSource来读取模拟的数据库数据。为了提高读写速度,我们在DBDataSource上添加了CacheDataSource这个装饰器。在实际应用中,通过CacheDataSource装饰后的DBDataSource模拟实现数据的缓存处理逻辑。

在以上示例中,装饰器增强了DBDataSource读取数据库数据的性能,同时增强了代码的灵活性和扩展性。

模板方法模式

模板方法模式是一种行为型设计模式,在Java中的应用较为广泛。模板方法模式定义了一个算法的骨架,而将具体的实现步骤延迟到子类中实现。以下是几个适用于模板方法模式的业务场景和示例代码:

  1. 搭建框架:在Java中,很多框架都采用了模板方法模式。例如,Servlet框架的设计中,我们需要重写doGet()和doPost()方法来实现具体的业务处理,但是其他很多方法(如init()和destroy())我们并不需要实现,只需要使用默认的实现即可。
public abstract class HttpServlet implements Servlet {
    protected void service(HttpServletRequest request, HttpServletResponse response) {
        String method = request.getMethod();
        if ("GET".equalsIgnoreCase(method)) {
            doGet(request, response);
        } else if ("POST".equalsIgnoreCase(method)) {
            doPost(request, response);
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        throw new ServletException("GET method not supported");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) {
        throw new ServletException("POST method not supported");
    }
}

在以上示例中,我们定义了一个HttpServlet抽象类,并实现了service方法。在service方法中,我们判断请求类型,如果是GET请求,则调用doGet方法;如果是POST请求,则调用doPost方法。而doGet和doPost方法在抽象类中只是定义了方法签名,具体实现则由子类去实现。

  1. 数据库处理:在Java中,很多数据库操作都是基于模板方法模式实现的。例如,我们可以定义一个JdbcTemplate类,为各种数据库操作提供模板方法,而将具体的实现交给子类进行实现。
public abstract class JdbcTemplate {
    public final void update(String sql) {
        try (Connection conn = getConnection()) {
            Statement stmt = conn.createStatement();
            stmt.executeUpdate(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    protected abstract Connection getConnection();
}

在以上示例中,我们定义了一个JdbcTemplate抽象类,并实现了update方法。在update方法中,我们首先调用抽象方法getConnection()获取连接,然后执行SQL语句。getConnection()方法则由子类实现,根据具体的数据库类型实现不同的数据连接池。

  1. 游戏开发:在游戏开发中,很多游戏都采用了模板方法模式来实现游戏场景、物品、角色等的生成。例如,我们可以模拟一个机器人打游戏的场景:
public abstract class GameRobot {
    public final void create() {
        assemble();
        startEngine();
        startPlay();
    }

    protected abstract void assemble();

    protected void startEngine() {
        System.out.println("Engine started...");
    }

    protected void startPlay() {
        System.out.println("Start playing...");
    }
}

public class FighterRobot extends GameRobot {
    @Override
    protected void assemble() {
        System.out.println("Assembling fighter robot...");
    }
}

public class GuardianRobot extends GameRobot {
    @Override
    protected void assemble() {
        System.out.println("Assembling guardian robot...");
    }
}

在以上示例中,我们定义了一个GameRobot抽象类,并实现了create方法。在create方法中,我们首先调用assemble方法组装机器人,然后启动引擎和开始游戏。assemble方法则由子类实现,实现不同机器人类型的组装逻辑。

桥接模式

桥接模式适用于以下场景:

  1. 当一个类需要在多个维度上进行变化,而这些维度可以独立地扩展时。

  2. 当一个系统需要在运行时动态地选择不同的实现时。

  3. 当一个抽象类有多个实现时,且这些实现可以独立于抽象类进行扩展。

业务场景:

  1. 消息发送器:不同的消息可以通过不同的方式发送,比如短信、邮件、微信等,而每种方式又可以通过不同的平台发送,比如邮件可以通过Outlook、Gmail等发出。可以通过桥接模式将消息发送器和发送平台进行解耦。

  2. 图形界面控件:图形界面控件可以有不同的外观样式,比如按钮可以是方形、圆形、椭圆形等。可以通过桥接模式将控件的外观样式和控件本身进行解耦。

代码示例:

public interface SendMessage { void send(String message); }

public class SmsSendMessage implements SendMessage { @Override public void send(String message) { System.out.println("通过短信发送消息:" + message); } }

public class EmailSendMessage implements SendMessage { @Override public void send(String message) { System.out.println("通过邮件发送消息:" + message); } }

public interface SendPlatform { void sendTo(String to, String message); }

public class OutlookSendPlatform implements SendPlatform { @Override public void sendTo(String to, String message) { System.out.println("使用Outlook发送邮件:" + to + ",内容:" + message); } }

public class GmailSendPlatform implements SendPlatform { @Override public void sendTo(String to, String message) { System.out.println("使用Gmail发送邮件:" + to + ",内容:" + message); } }

public abstract class MessageSender { protected SendPlatform sendPlatform;

public abstract void send(String message, String to);

public void setSendPlatform(SendPlatform sendPlatform) {
    this.sendPlatform = sendPlatform;
}

}

public class SmsMessageSender extends MessageSender { private SendMessage sendMessage;

public SmsMessageSender(SendMessage sendMessage) {
    this.sendMessage = sendMessage;
}

@Override
public void send(String message, String to) {
    sendMessage.send(message);
}

}

public class EmailMessageSender extends MessageSender { private SendMessage sendMessage;

public EmailMessageSender(SendMessage sendMessage) {
    this.sendMessage = sendMessage;
}

@Override
public void send(String message, String to) {
    sendPlatform.sendTo(to, message);
}

}

public class Client { public static void main(String[] args) { SendMessage smsSendMessage = new SmsSendMessage(); SendMessage emailSendMessage = new EmailSendMessage();

    SendPlatform outlookSendPlatform = new OutlookSendPlatform();
    SendPlatform gmailSendPlatform = new GmailSendPlatform();

    MessageSender smsMessageSender = new SmsMessageSender(smsSendMessage);
    MessageSender outlookEmailSender = new EmailMessageSender(emailSendMessage);
    MessageSender gmailEmailSender = new EmailMessageSender(emailSendMessage);

    smsMessageSender.send("Hello World", "18888888888");

    outlookEmailSender.setSendPlatform(outlookSendPlatform);
    outlookEmailSender.send("Hello World", "youremail@outlook.com");

    gmailEmailSender.setSendPlatform(gmailSendPlatform);
    gmailEmailSender.send("Hello World", "youremail@gmail.com");
}

}

建造者模式

在电商项目中,建造者模式适用于以下场景:

  1. 订单生成:订单包含多个属性,比如商品种类、数量、价格、支付方式等,根据不同的属性组合可以生成不同的订单类型,建造者模式可以让用户灵活地组合不同的属性生成不同的订单。

  2. 商品搜索:根据用户选择的不同的条件可以搜索出不同类型的商品列表,比如按照价格排序、按照销量排序、按照品牌筛选等,这些查询条件也可以通过建造者模式来构建。

代码示例:

  1. 订单生成

定义 Order 类,包含多个属性,比如商品列表、收货地址、运费、总价等。

public class Order {
    private List<Item> items;
    private String address;
    private double shippingFee;
    private double totalPrice;

    // 省略 getter 和 setter 方法
}

public class Item {
    private String name;
    private double price;
    private int quantity;

    // 省略 getter 和 setter 方法
}

定义 OrderBuilder 接口,包含多个用来设置 Order 属性的方法。

public interface OrderBuilder {
    void addItem(String name, double price, int quantity);
    void setAddress(String address);
    void setShippingFee(double shippingFee);
    void setTotalPrice(double totalPrice);
    Order build();
}

定义具体的 OrderBuilder 实现类,实现 OrderBuilder 接口中的所有方法。

public class ConcreteOrderBuilder implements OrderBuilder {
    private Order order;

    public ConcreteOrderBuilder() {
        order = new Order();
        order.setItems(new ArrayList<>());
    }

    @Override
    public void addItem(String name, double price, int quantity) {
        Item item = new Item();
        item.setName(name);
        item.setPrice(price);
        item.setQuantity(quantity);
        order.getItems().add(item);
    }

    @Override
    public void setAddress(String address) {
        order.setAddress(address);
    }

    @Override
    public void setShippingFee(double shippingFee) {
        order.setShippingFee(shippingFee);
    }

    @Override
    public void setTotalPrice(double totalPrice) {
        order.setTotalPrice(totalPrice);
    }

    @Override
    public Order build() {
        return order;
    }
}

定义 Director 类,主要负责调用 OrderBuilder 中的方法生成订单。

public class Director {
    private OrderBuilder orderBuilder;

    public Director(OrderBuilder orderBuilder) {
        this.orderBuilder = orderBuilder;
    }

    public Order createOrder() {
        orderBuilder.addItem("商品1", 100.0, 1);
        orderBuilder.addItem("商品2", 200.0, 2);
        orderBuilder.setAddress("广州市天河区");
        orderBuilder.setShippingFee(10.0);
        orderBuilder.setTotalPrice(510.0);
        return orderBuilder.build();
    }
}

使用方式:

ConcreteOrderBuilder orderBuilder = new ConcreteOrderBuilder();
Director director = new Director(orderBuilder);
Order order = director.createOrder();
System.out.println(order);
  1. 商品搜索

定义 Product 类,包含多个属性,比如商品名称、价格、销量、品牌、类别等。

public class Product {
    private String name;
    private double price;
    private int sales;
    private String brand;
    private String category;

    // 省略 getter 和 setter 方法
}

定义 ProductSearchBuilder 接口,包含多个用来设置 Product 查询条件的方法。

public interface ProductSearchBuilder {
    void setName(String name);
    void setPrice(double price);
    void setSales(int sales);
    void setBrand(String brand);
    void setCategory(String category);
    List<Product> search();
}

定义具体的 ProductSearchBuilder 实现类,实现 ProductSearchBuilder 接口中的所有方法。

public class ConcreteProductSearchBuilder implements ProductSearchBuilder {
    private ProductDAO productDAO;
    private Map<String, Object> conditions;

    public ConcreteProductSearchBuilder() {
        productDAO = new ProductDAO();
        conditions = new HashMap<>();
    }

    @Override
    public void setName(String name) {
        conditions.put("name", name);
    }

    @Override
    public void setPrice(double price) {
        conditions.put("price", price);
    }

    @Override
    public void setSales(int sales) {
        conditions.put("sales", sales);
    }

    @Override
    public void setBrand(String brand) {
        conditions.put("brand", brand);
    }

    @Override
    public void setCategory(String category) {
        conditions.put("category", category);
    }

    @Override
    public List<Product> search() {
        return productDAO.search(conditions);
    }
}

定义 ProductDAO 类,模拟从数据库中查询商品信息的操作。

public class ProductDAO {
    public List<Product> search(Map<String, Object> conditions) {
        // 查询数据库并返回结果
        ...
    }
}

使用方式:

ConcreteProductSearchBuilder productSearchBuilder = new ConcreteProductSearchBuilder();
productSearchBuilder.setBrand("品牌1");
productSearchBuilder.setPrice(100.0);
productSearchBuilder.setSales(1000);
List<Product> products = productSearchBuilder.search();
System.out.println(products);

中介者模式

在电商项目中,中介者模式适用于以下场景:

  1. 购物车:多个商品可以加入到购物车中,并且购物车中的商品数量、总价都需要根据不同商品的属性进行计算,中介者模式可以将购物车作为中介者,将商品类和购物车类解耦,使得商品的修改不会影响到购物车的计算。

  2. 支付:支付需要减少商品库存、增加销量、记录交易信息等多个步骤,中介者模式可以将这些操作统一封装在支付中心,让支付中心作为中介者实现各个环节之间的协作。

代码示例:

  1. 购物车

定义 Product 类,包含多个属性,比如商品名称、价格、数量等。

public class Product {
    private String name;
    private double price;
    private int quantity;

    // 省略 getter 和 setter 方法
}

定义 ShoppingCart 类,实现购物车的计算和操作。

public class ShoppingCart {
    private Map<String, Product> items;

    public ShoppingCart() {
        items = new HashMap<>();
    }

    public void addItem(Product product) {
        String key = product.getName();
        if (!items.containsKey(key)) {
            items.put(key, product);
        } else {
            Product p = items.get(key);
            p.setQuantity(p.getQuantity() + product.getQuantity());
        }
    }

    public void removeItem(Product product) {
        String key = product.getName();
        if (items.containsKey(key)) {
            Product p = items.get(key);
            p.setQuantity(p.getQuantity() - product.getQuantity());
            if (p.getQuantity() <= 0) {
                items.remove(key);
            }
        }
    }

    public double getTotalPrice() {
        double totalPrice = 0.0;
        for (Product product : items.values()) {
            totalPrice += product.getPrice() * product.getQuantity();
        }
        return totalPrice;
    }

    public int getTotalQuantity() {
        int totalQuantity = 0;
        for (Product product : items.values()) {
            totalQuantity += product.getQuantity();
        }
        return totalQuantity;
    }
}
  1. 支付

定义 PaymentCenter 接口,包含多个用来处理支付的抽象方法。

public interface PaymentCenter {
    void reduceStock(String productId, int quantity);
    void increaseSales(String productId, int quantity);
    void recordTransaction(String transactionId, double amount);
    void pay(String transactionId, double amount);
}

定义具体的 PaymentCenter 实现类,实现 PaymentCenter 接口中的所有方法。

public class ConcretePaymentCenter implements PaymentCenter {
    private ProductService productService;
    private TransactionService transactionService;

    public ConcretePaymentCenter() {
        productService = new ProductService();
        transactionService = new TransactionService();
    }

    @Override
    public void reduceStock(String productId, int quantity) {
        productService.reduceStock(productId, quantity);
    }

    @Override
    public void increaseSales(String productId, int quantity) {
        productService.increaseSales(productId, quantity);
    }

    @Override
    public void recordTransaction(String transactionId, double amount) {
        transactionService.recordTransaction(transactionId, amount);
    }

    @Override
    public void pay(String transactionId, double amount) {
        transactionService.pay(transactionId, amount);
    }
}

定义 ProductService 类,模拟从数据库中修改商品信息的操作。

public class ProductService {
    public void reduceStock(String productId, int quantity) {
        // 查询数据库并修改库存
        ...
    }

    public void increaseSales(String productId, int quantity) {
        // 查询数据库并修改销量
        ...
    }
}

定义 TransactionService 类,模拟记录交易信息和支付操作。

public class TransactionService {
    public void recordTransaction(String transactionId, double amount) {
        // 记录交易信息
        ...
    }

    public void pay(String transactionId, double amount) {
        // 调用第三方支付接口进行支付
        ...
    }
}

使用方式:

ConcretePaymentCenter paymentCenter = new ConcretePaymentCenter();
paymentCenter.reduceStock("商品1", 1);
paymentCenter.increaseSales("商品1", 1);
paymentCenter.recordTransaction("xxxxxx", 100.0);
paymentCenter.pay("xxxxxx", 100.0);

访问者模式

在电商项目中,访问者模式适用于以下场景:

  1. 商品评价:不同的用户对商品的评价可能会有不同的侧重点,比如有些用户更注重商品的品质,有些用户更注重商品的价格等,访问者模式可以让评价者根据自己的需求对商品进行不同的评价。

  2. 数据统计:电商平台需要对用户进行统计分析,比如统计用户的地域分布、消费行为等,访问者模式可以让数据统计者对不同的用户信息进行不同的统计分析。

代码示例:

  1. 商品评价

定义 Product 类,包含多个属性,比如商品名称、价格、品质等。

public class Product {
    private String name;
    private double price;
    private double qualityScore;
    private double priceScore;

    // 省略 getter 和 setter 方法
}

定义 Visitor 接口,包含用来评价商品的抽象方法。

public interface Visitor {
    void visitByQuality(Product product);
    void visitByPrice(Product product);
}

定义具体的 Visitor 实现类,实现 Visitor 接口中的评价方法。

public class ConcreteVisitor implements Visitor {
    @Override
    public void visitByQuality(Product product) {
        double score = product.getQualityScore();
        if (score >= 9.0) {
            System.out.println("好评");
        } else if (score >= 7.0) {
            System.out.println("中评");
        } else {
            System.out.println("差评");
        }
    }

    @Override
    public void visitByPrice(Product product) {
        double score = product.getPriceScore();
        if (score >= 9.0) {
            System.out.println("好评");
        } else if (score >= 7.0) {
            System.out.println("中评");
        } else {
            System.out.println("差评");
        }
    }
}

定义 ProductList 类,包含多个 Product 对象,提供接受 Visitor 的方法。

public class ProductList {
    private List<Product> products;

    public ProductList() {
        products = new ArrayList<>();
    }

    public void addProduct(Product product) {
        products.add(product);
    }

    public void removeProduct(Product product) {
        products.remove(product);
    }

    public void accept(Visitor visitor) {
        for (Product product : products) {
            visitor.visitByQuality(product);
            visitor.visitByPrice(product);
        }
    }
}

使用方式:

ProductList productList = new ProductList();
productList.addProduct(new Product("商品1", 100.0, 8.0, 9.0));
productList.addProduct(new Product("商品2", 200.0, 9.0, 7.0));
ConcreteVisitor visitor = new ConcreteVisitor();
productList.accept(visitor);
  1. 数据统计

定义 User 类,包含多个属性,比如用户名、地域、订单数量等。

public class User {
    private String username;
    private String region;
    private int orderCount;

    // 省略 getter 和 setter 方法
}

定义 Visitor 接口,包含用来统计用户信息的抽象方法。

public interface Visitor {
    void visitByRegion(User user);
    void visitByOrderCount(User user);
}

定义具体的 Visitor 实现类,实现 Visitor 接口中的统计方法。

public class ConcreteVisitor implements Visitor {
    private Map<String, Integer> regionCountMap;
    private int topUsers;

    public ConcreteVisitor() {
        regionCountMap = new HashMap<>();
        topUsers = 0;
    }

    @Override
    public void visitByRegion(User user) {
        String region = user.getRegion();
        int count = regionCountMap.getOrDefault(region, 0);
        regionCountMap.put(region, count + 1);
    }

    @Override
    public void visitByOrderCount(User user) {
        topUsers += (user.getOrderCount() >= 10) ? 1 : 0;
    }

    public Map<String, Integer> getRegionCountMap() {
        return regionCountMap;
    }

    public int getTopUsers() {
        return topUsers;
    }
}

定义 UserList 类,包含多个 User 对象,提供接受 Visitor 的方法。

public class UserList {
    private List<User> users;

    public UserList() {
        users = new ArrayList<>();
    }

    public void addUser(User user) {
        users.add(user);
    }

    public void removeUser(User user) {
        users.remove(user);
    }

    public void accept(Visitor visitor) {
        for (User user : users) {
            visitor.visitByRegion(user);
            visitor.visitByOrderCount(user);
        }
    }
}

使用方式:

UserList userList = new UserList();
userList.addUser(new User("user1", "广州", 5));
userList.addUser(new User("user2", "广州", 8));
userList.addUser(new User("user3", "深圳", 12));
userList.addUser(new User("user4", "北京", 15));
ConcreteVisitor visitor = new ConcreteVisitor();
userList.accept(visitor);
Map<String, Integer> regionCountMap = visitor.getRegionCountMap();
int topUsers = visitor.getTopUsers();
System.out.println(regionCountMap);
System.out.println(topUsers);