• 作者:老汪软件技巧
  • 发表时间:2024-09-30 21:01
  • 浏览量:

定义

外观模式(Facade Pattern)是一种结构型设计模式,它为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易使用。外观模式通过将复杂的子系统封装在一个外观类中,对外提供简单易用的接口,隐藏了子系统的复杂性。

以下是外观模式的主要特点和定义:

一、主要角色

Facade(外观角色) :

Subsystem classes(子系统角色) :

业务类图

classDiagram
    class OrderFacade {
        -OrderService orderService
        -InventoryService inventoryService
        -PaymentService paymentService
        +placeOrder(String, int, double) : void
    }
    class OrderService {
        +createOrder(String, int) : void
    }
    class OrderServiceImpl {
        +createOrder(String, int) : void
    }
    class InventoryService {
        +checkInventory(String, int) : boolean
    }
    class InventoryServiceImpl {
        +checkInventory(String, int) : boolean
    }
    class PaymentService {
        +processPayment(double) : void
    }
    class PaymentServiceImpl {
        +processPayment(double) : void
    }
    OrderFacade --> OrderService
    OrderFacade --> InventoryService
    OrderFacade --> PaymentService
    OrderServiceImpl --> OrderService
    InventoryServiceImpl --> InventoryService
    PaymentServiceImpl --> PaymentService
    OrderController --> OrderFacade

代码

假设我们正在开发一个电子商务系统,其中有订单管理、库存管理和支付系统等多个子系统。为了简化客户端(例如前端应用或其他服务)对这些子系统的操作,我们可以使用外观模式创建一个订单服务外观类。

1. 定义子系统的接口和实现类

订单管理接口和实现类:

public interface OrderService {
    void createOrder(String productId, int quantity);
}
@Service
public class OrderServiceImpl implements OrderService {
    @Override
    public void createOrder(String productId, int quantity) {
        System.out.println("Order created for product " + productId + " with quantity " + quantity);
    }
}

库存管理接口和实现类:

public interface InventoryService {
    boolean checkInventory(String productId, int quantity);
}
@Service
public class InventoryServiceImpl implements InventoryService {
    @Override
    public boolean checkInventory(String productId, int quantity) {
        // 模拟库存检查逻辑
        return true;
    }
}

支付系统接口和实现类:

public interface PaymentService {
    void processPayment(double amount);
}
@Service
public class PaymentServiceImpl implements PaymentService {
    @Override
    public void processPayment(double amount) {
        System.out.println("Payment of " + amount + " processed.");
    }
}

2. 创建外观类

@Service
public class OrderFacade {
    private final OrderService orderService;
    private final InventoryService inventoryService;
    private final PaymentService paymentService;
    @Autowired
    public OrderFacade(OrderService orderService, InventoryService inventoryService, PaymentService paymentService) {
        this.orderService = orderService;
        this.inventoryService = inventoryService;
        this.paymentService = paymentService;
    }
    public void placeOrder(String productId, int quantity, double price) {
        if (inventoryService.checkInventory(productId, quantity)) {
            orderService.createOrder(productId, quantity);
            paymentService.processPayment(quantity * price);
        } else {
            System.out.println("Insufficient inventory for product " + productId);
        }
    }
}

3. 使用外观类

在其他服务或控制器中,可以直接使用这个外观类来处理订单操作,而无需直接与各个子系统交互。

@RestController
public class OrderController {
    private final OrderFacade orderFacade;
    @Autowired
    public OrderController(OrderFacade orderFacade) {
        this.orderFacade = orderFacade;
    }
    @PostMapping("/placeOrder")
    public void placeOrder(@RequestParam String productId, @RequestParam int quantity, @RequestParam double price) {
        orderFacade.placeOrder(productId, quantity, price);
    }
}

_外观模式类图_外观模式符合开闭原则吗

在这个案例中,OrderFacade外观类封装了订单管理、库存管理和支付系统的操作,为客户端提供了一个简单统一的接口来处理订单相关的业务逻辑,隐藏了各个子系统的复杂性。

框架中的使用spring

一、Spring JDBC 中的JdbcTemplate

JdbcTemplate为使用 JDBC 进行数据库操作提供了一个简化的外观。它封装了底层的 JDBC 复杂性,如连接管理、资源释放、异常处理等,为开发者提供了一组简单易用的方法来执行 SQL 查询、更新和存储过程调用等操作。

例如:

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
public class JdbcTemplateExample {
    public static void main(String[] args) {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
        dataSource.setUsername("root");
        dataSource.setPassword("password");
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        int rowsAffected = jdbcTemplate.update("INSERT INTO mytable (name, value) VALUES (?,?)", "John", 100);
        System.out.println("Rows affected: " + rowsAffected);
    }
}

这里,JdbcTemplate作为一个外观,隐藏了底层 JDBC 操作的复杂性,让开发者可以更专注于业务逻辑而不是繁琐的数据库连接和操作细节。

二、Spring 的事务管理

Spring 的事务管理机制也可以看作是一种外观模式的应用。它为开发者提供了一个统一的方式来管理事务,而无需直接处理底层的数据库事务机制。

例如,使用@Transactional注解来标记一个方法需要事务管理:

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class MyService {
    @Transactional
    public void performTransactionalOperation() {
        // 数据库操作逻辑
    }
}

Spring 的事务管理外观将底层的事务处理细节(如事务的开始、提交、回滚等)封装起来,开发者只需要通过注解或编程方式使用事务管理功能,而无需了解底层的事务实现机制。

综上所述,Spring 在多个方面应用了外观模式,为开发者提供了更简单、易用的接口,隐藏了底层的复杂性。

总结

在spring开发中,实际上就是在service和controller之间加了一层facade service

一、使用场景

当你需要为一个复杂的子系统提供一个简单的接口时,可以使用外观模式。例如,一个软件系统包含多个复杂的模块,为了方便其他模块或用户使用这些模块,可以创建一个外观类,提供一组简单的方法来调用这些模块的功能。当你希望减少系统的依赖关系时,可以使用外观模式。外观模式将客户端与子系统解耦,客户端只需要与外观类交互,而不需要了解子系统的内部结构和实现细节。当你需要分层设计系统时,可以使用外观模式。外观模式可以将复杂的系统分为多个层次,每个层次提供不同的功能和服务,外观类作为系统的入口点,负责协调各个层次的交互。

二、优点

简化了客户端的调用:客户端只需要与外观类交互,而不需要了解子系统的内部结构和实现细节,降低了客户端的使用难度。减少了系统的依赖关系:外观模式将客户端与子系统解耦,降低了系统之间的耦合度,提高了系统的可维护性和可扩展性。提高了系统的灵活性:可以根据需要灵活地增加或删除子系统的功能,而不会影响客户端的使用。

三、缺点

不符合开闭原则:如果要修改外观类的接口,可能需要修改所有客户端的代码。可能会降低系统的性能:外观类可能会成为系统的瓶颈,如果外观类的实现过于复杂,可能会影响系统的性能。