MST
星途 面试题库

面试题:Java建造者模式在复杂领域模型构建中的优化

在构建一个复杂的Java领域模型时,可能涉及到多个子组件的构建以及构建过程中的复杂逻辑判断。假设我们要构建一个电商订单领域模型,订单包含商品列表、用户信息、配送信息等,商品又有不同的类别和属性。请详细说明如何运用建造者模式,并针对构建过程中可能出现的性能问题和资源浪费问题,提出优化方案。
41.8万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

1. 建造者模式在电商订单领域模型中的应用

  1. 定义产品类 - 订单类
public class Order {
    private List<Product> productList;
    private User user;
    private DeliveryInfo deliveryInfo;

    // 省略getter和setter方法
    public void setProductList(List<Product> productList) {
        this.productList = productList;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public void setDeliveryInfo(DeliveryInfo deliveryInfo) {
        this.deliveryInfo = deliveryInfo;
    }
}
  1. 定义商品类
public class Product {
    private String category;
    private Map<String, String> properties;

    // 省略getter和setter方法
    public void setCategory(String category) {
        this.category = category;
    }

    public void setProperties(Map<String, String> properties) {
        this.properties = properties;
    }
}
  1. 定义用户类
public class User {
    private String name;
    private String contact;

    // 省略getter和setter方法
    public void setName(String name) {
        this.name = name;
    }

    public void setContact(String contact) {
        this.contact = contact;
    }
}
  1. 定义配送信息类
public class DeliveryInfo {
    private String address;
    private String deliveryMethod;

    // 省略getter和setter方法
    public void setAddress(String address) {
        this.address = address;
    }

    public void setDeliveryMethod(String deliveryMethod) {
        this.deliveryMethod = deliveryMethod;
    }
}
  1. 定义建造者接口
public interface OrderBuilder {
    void buildProductList();
    void buildUser();
    void buildDeliveryInfo();
    Order getOrder();
}
  1. 具体建造者实现
public class ConcreteOrderBuilder implements OrderBuilder {
    private Order order = new Order();

    @Override
    public void buildProductList() {
        List<Product> productList = new ArrayList<>();
        // 假设从数据库或其他数据源获取商品信息
        Product product1 = new Product();
        product1.setCategory("Electronics");
        Map<String, String> properties1 = new HashMap<>();
        properties1.put("brand", "Apple");
        properties1.put("model", "iPhone 14");
        product1.setProperties(properties1);
        productList.add(product1);

        order.setProductList(productList);
    }

    @Override
    public void buildUser() {
        User user = new User();
        user.setName("John Doe");
        user.setContact("john@example.com");
        order.setUser(user);
    }

    @Override
    public void buildDeliveryInfo() {
        DeliveryInfo deliveryInfo = new DeliveryInfo();
        deliveryInfo.setAddress("123 Main St");
        deliveryInfo.setDeliveryMethod("Express");
        order.setDeliveryInfo(deliveryInfo);
    }

    @Override
    public Order getOrder() {
        return order;
    }
}
  1. 导演类
public class OrderDirector {
    private OrderBuilder orderBuilder;

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

    public Order constructOrder() {
        orderBuilder.buildProductList();
        orderBuilder.buildUser();
        orderBuilder.buildDeliveryInfo();
        return orderBuilder.getOrder();
    }
}
  1. 使用示例
public class Main {
    public static void main(String[] args) {
        OrderBuilder orderBuilder = new ConcreteOrderBuilder();
        OrderDirector orderDirector = new OrderDirector(orderBuilder);
        Order order = orderDirector.constructOrder();
    }
}

2. 性能问题及优化方案

  1. 性能问题
    • 重复计算:在构建商品列表时,如果每次获取商品信息都从数据库查询,且查询条件不变,会产生重复计算。
    • 资源浪费:如果构建过程中有临时对象创建,但这些对象在构建完成后不再使用,会造成资源浪费。例如,在构建商品属性的Map对象时,如果构建失败,但已经创建了大量这样的Map对象。
  2. 优化方案
    • 缓存机制
      • 商品信息缓存:使用缓存框架(如Guava Cache或Redis)来缓存商品信息。在构建商品列表时,先从缓存中获取商品信息,如果缓存中没有,则查询数据库并将结果存入缓存。例如,使用Guava Cache:
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

public class ProductCache {
    private static final Cache<String, Product> productCache = CacheBuilder.newBuilder()
           .maximumSize(1000)
           .build();

    public static Product getProductFromCache(String productId) {
        return productCache.getIfPresent(productId);
    }

    public static void putProductToCache(String productId, Product product) {
        productCache.put(productId, product);
    }
}

buildProductList方法中使用缓存:

@Override
public void buildProductList() {
    List<Product> productList = new ArrayList<>();
    String productId = "123";
    Product product = ProductCache.getProductFromCache(productId);
    if (product == null) {
        // 从数据库查询
        product = new Product();
        product.setCategory("Electronics");
        Map<String, String> properties1 = new HashMap<>();
        properties1.put("brand", "Apple");
        properties1.put("model", "iPhone 14");
        product.setProperties(properties1);
        ProductCache.putProductToCache(productId, product);
    }
    productList.add(product);
    order.setProductList(productList);
}
  • 对象复用
    • 对象池:对于一些频繁创建和销毁的对象,如数据库连接对象(如果构建过程中需要数据库操作),可以使用对象池技术。例如,使用Apache Commons Pool来管理数据库连接对象。
    • 避免不必要的对象创建:在构建过程中,尽量复用已有的对象。例如,如果订单构建过程中需要获取用户信息,且该用户信息在其他地方已经获取并存在内存中,可以直接复用该用户对象,而不是重新创建。
  • 构建逻辑优化
    • 减少复杂逻辑中的嵌套:如果构建过程中有复杂的逻辑判断,尽量简化嵌套结构,提高代码的可读性和执行效率。例如,使用策略模式来替代复杂的if - else逻辑,将不同的构建策略封装成独立的类。
    • 延迟加载:对于一些不是立即需要的组件(如订单中的一些附加信息),可以采用延迟加载的方式,在真正需要时再进行构建。例如,订单中的商品评价信息,在订单构建时可以先不加载,当用户查看订单评价时再进行加载。