【读书活动感悟分享】—模式冲锋号—《设计模式:可复用面向对象软件的基础》单例与原型模式实现与对比_话题

【读书活动感悟分享】—模式冲锋号—《设计模式:可复用面向对象软件的基础》单例与原型模式实现与对比

2025-11-14 21:20:55
0
92

一、单例模式代码实现与比对:
1.四种核心实现方案代码
(1)饿汉式(线程安全,启动即加载)

// (饿汉式单例)
public class TeldDispatchCenter
{
    // 类加载时直接初始化实例(线程安全)
    private static final TeldDispatchCenter INSTANCE = new TeldDispatchCenter();

    // 私有构造器防止外部创建
    private TeldDispatchCenter()
    {
        // 初始化调度规则、充电桩连接池等(耗时操作)
        initDispatchRules();
    }

    // 全局访问点
    public static TeldDispatchCenter getInstance()
    {
        return INSTANCE;
    }

    // 核心业务:分配充电桩
    public Charger assignCharger(User user)
    {
        // 调度逻辑:查询空闲桩、匹配用户位置等
        return new Charger();
    }

    private void initDispatchRules()
    {
        // 加载全国充电桩布局、峰谷电价规则等
        System.out.println("初始化调度中心规则库...");
    }
}

(2)懒汉式(非线程安全,按需加载)

// (懒汉式单例-非线程安全)
public class TeldDispatchCenter
{
    private static TeldDispatchCenter instance;

    private TeldDispatchCenter()
    {
        initDispatchRules();
    }

    // 多线程下可能创建多个实例(风险)
    public static TeldDispatchCenter getInstance()
    {
        if (instance == null)
        {
            instance = new TeldDispatchCenter();
        }
        return instance;
    }

    // 业务方法同上...
}

(3)双重检查锁(DCL,线程安全+按需加载)

// (DCL单例)
public class TeldDispatchCenter {
    // volatile防止指令重排序,确保实例可见性
    private static volatile TeldDispatchCenter instance;
    
    private TeldDispatchCenter() {
        initDispatchRules();
    }
    
    public static TeldDispatchCenter getInstance() {
        // 第一次检查:避免频繁加锁
        if (instance == null) {
            synchronized (TeldDispatchCenter.class) {
                // 第二次检查:防止多线程等待锁后重复创建
                if (instance == null) {
                    instance = new TeldDispatchCenter();
                }
            }
        }
        return instance;
    }
    
    // 业务方法同上...
}

(4)枚举单例(最优线程安全,防反射破坏)

// (枚举单例)
public enum TeldDispatchCenter {
    INSTANCE;
    
    // 枚举构造器默认私有,且无法通过反射创建
    TeldDispatchCenter() {
        initDispatchRules();
    }
    
    // 全局访问点(直接通过TeldDispatchCenter.INSTANCE调用)
    public Charger assignCharger(User user) {
        return new Charger();
    }
    
    private void initDispatchRules() {
        System.out.println("枚举单例初始化调度规则...");
    }
}


2.四种实现方案比对表

3.特来电实际选型建议
调度中心/电价配置:选枚举单例,因需防恶意反射修改配置,且启动时加载不影
响核心流程;
HTTP连接池:选双重检查锁,兼顾高并发下的懒加载和线程安全,避免启动时占
用过多资源。


二、原型模式代码实现与比对:充电桩实例创建场景
1.浅拷贝与深拷贝代码实现
(1)浅拷贝(原型接口+Cloneable)

// 充电桩基础类(实现Cloneable接口)
public class Charger implements Cloneable {
    // 基本数据类型(浅拷贝会复制值)
    private String chargerId;
    private int power; // 功率(kW)
    private String location;
    // 引用数据类型(浅拷贝仅复制引用,共享对象)
    private ChargerConfig config; // 包含充电协议、安全规则等
    
    // 构造器:初始化基础属性
    public Charger(String chargerId, int power, String location) {
        this.chargerId = chargerId;
        this.power = power;
        this.location = location;
        this.config = new ChargerConfig("GB/T 18487.1-2015", true); // 国标协议
    }
    
    // 浅拷贝实现
    @Override
    protected Charger clone() throws CloneNotSupportedException {
        return (Charger) super.clone();
    }
    
    // Getter/Setter...
}
// 充电桩配置类(引用类型)
class ChargerConfig {
    private String protocol; // 充电协议
    private boolean isSafetyProtected; // 是否开启安全保护
    
    public ChargerConfig(String protocol, boolean isSafetyProtected) {
        this.protocol = protocol;
        this.isSafetyProtected = isSafetyProtected;
    }
    
    // Getter/Setter...
}

(2)深拷贝(两种实现方式)

// 方式1:通过Cloneable递归拷贝引用类型
public class Charger implements Cloneable {
    // 同上...
    
    // 深拷贝实现
    @Override
    protected Charger clone() throws CloneNotSupportedException {
        Charger cloned = (Charger) super.clone();
        // 对引用类型单独克隆,实现深拷贝
        cloned.config = new ChargerConfig(
            this.config.getProtocol(), 
            this.config.isSafetyProtected()
        );
        return cloned;
    }
}
// 方式2:通过序列化(Serializable)实现深拷贝
public class Charger implements Serializable {
    // 同上...(实现Serializable接口,无抽象方法)
    
    // 深拷贝:序列化+反序列化
    public Charger deepCloneBySerial() throws IOException, ClassNotFoundException {
        // 1. 序列化:将对象写入流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        
        // 2. 反序列化:从流中读取新对象
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (Charger) ois.readObject();
    }
}


2.浅拷贝vs深拷贝:

// 测试代码:对比浅拷贝与深拷贝的引用共享问题
public class ChargerCloneTest {
    public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
        // 1. 创建原型对象(高速服务区充电桩)
        Charger prototype = new Charger("CS-1001", 120, "G15高速杭州服务区");
        
        // 2. 浅拷贝:创建小区充电桩(修改功率为7kW)
        Charger shallowClone = prototype.clone();
        shallowClone.setChargerId("CS-2001");
        shallowClone.setPower(7);
        shallowClone.setLocation("杭州未来科技城小区");
        // 问题:修改拷贝对象的config,原型对象的config也会变(引用共享)
        shallowClone.getConfig().setProtocol("GB/T 18487.1-2023");
        System.out.println("原型config协议:" + prototype.getConfig().getProtocol()); // 输出2023(被修改)
        
        // 3. 深拷贝:创建商业综合体充电桩
        Charger deepClone = prototype.deepCloneBySerial();
        deepClone.setChargerId("CS-3001");
        deepClone.setPower(60);
        deepClone.setLocation("杭州万象城");
        // 正常:修改深拷贝对象的config,原型不受影响
        deepClone.getConfig().setProtocol("GB/T 18487.1-2015");
        System.out.println("原型config协议:" + prototype.getConfig().getProtocol()); // 输出2023(未被修改)
    }
}

3.特来电场景下的拷贝方式选型


三、模式协同代码:特来电支付流程中的单例+原型

// 1. 单例:HTTP连接池(管理支付接口连接)
public enum PaymentHttpPool {
    INSTANCE;
    
    private HttpClient httpClient;
    
    PaymentHttpPool() {
        // 初始化连接池:设置最大连接数、超时时间等
        httpClient = HttpClient.newBuilder()
                .connectTimeout(Duration.ofSeconds(3))
                .connectionPool(ConnectionPool.max(20))
                .build();
    }
    
    public HttpClient getClient() {
        return httpClient;
    }
}
// 2. 原型:充电订单(克隆空白订单填充数据)
public class ChargingOrder implements Serializable {
    private String orderId;
    private User user;
    private Charger charger;
    private BigDecimal amount;
    private LocalDateTime startTime;
    
    // 空白订单原型(默认初始化基础结构)
    public static ChargingOrder getPrototype() {
        ChargingOrder prototype = new ChargingOrder();
        prototype.setOrderId(UUID.randomUUID().toString().substring(0, 10)); // 生成默认订单号
        prototype.setStartTime(LocalDateTime.now());
        return prototype;
    }
    
    // 深拷贝:确保用户、充电桩信息隔离
    public ChargingOrder deepClone() throws IOException, ClassNotFoundException {
        // 序列化实现深拷贝(代码同前)
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        new ObjectOutputStream(bos).writeObject(this);
        return (ChargingOrder) new ObjectInputStream(
                new ByteArrayInputStream(bos.toByteArray())
        ).readObject();
    }
    
    // 填充订单数据
    public void fillOrderData(User user, Charger charger, BigDecimal amount) {
        this.user = user;
        this.charger = charger;
        this.amount = amount;
    }
    
    // 调用支付接口(依赖单例连接池)
    public boolean pay() {
        // 使用单例连接池发送支付请求
        HttpClient client = PaymentHttpPool.INSTANCE.getClient();
        // 支付逻辑:调用微信/支付宝接口...
        return true;
    }
    
    // Getter/Setter...
}
// 3. 协同调用:生成订单并支付
public class OrderService {
    public boolean createAndPayOrder(User user, Charger charger, BigDecimal amount) {
        try {
            // 步骤1:克隆空白订单原型
            ChargingOrder prototype = ChargingOrder.getPrototype();
            ChargingOrder order = prototype.deepClone();
            
            // 步骤2:填充订单数据
            order.fillOrderData(user, charger, amount);
            
            // 步骤3:使用单例连接池发起支付
            return order.pay();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}
分享者: 平台交付部_高广凯
评论


意见反馈