You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

外观设计模式(Facade):跨子系统传递MyClass类型的正确方式

子系统外观模式下的类型传递与解耦方案

是否应通过外观传递MyClass类型?

绝对不应该。直接传递子系统A的内部类MyClass会让子系统B依然强依赖A的实现细节,耦合度问题根本没解决——外观模式的核心价值就是隐藏子系统内部结构,降低外部依赖,传递内部类型完全违背了这个初衷。

正确的实现方式

根据MyClass的定位(纯数据载体/带业务行为)和子系统B的需求,有三种典型的解耦方案:

1. 定义独立数据传输对象(DTO)

如果MyClass只是纯数据载体,在外观层或独立的公共模块中定义与MyClass数据结构一致的DTO(比如MyClassDTO),由外观负责MyClass与DTO之间的转换,子系统B的方法参数换成DTO类型。

示例代码:

// 子系统A内部类(无需修改)
public class MyClass {
    private String name;
    private int age;
    // Getter/Setter
}

// 公共DTO(放在外观模块或公共包)
public class MyClassDTO {
    private String name;
    private int age;
    // Getter/Setter
}

// 子系统A的外观类
public class SubsystemAFacade {
    public MyClass createMyClass(String name, int age) {
        return new MyClass(name, age);
    }

    public MyClassDTO convertToDTO(MyClass myClass) {
        MyClassDTO dto = new MyClassDTO();
        dto.setName(myClass.getName());
        dto.setAge(myClass.getAge());
        return dto;
    }
}

// 子系统B的方法(修改为依赖DTO)
public class SubsystemB {
    public void processData(MyClassDTO dto) {
        System.out.println("处理数据:" + dto.getName() + ",年龄:" + dto.getAge());
    }
}

// 客户端调用
public class Client {
    public static void main(String[] args) {
        SubsystemAFacade facade = new SubsystemAFacade();
        MyClass myClass = facade.createMyClass("张三", 25);
        MyClassDTO dto = facade.convertToDTO(myClass);
        
        SubsystemB subsystemB = new SubsystemB();
        subsystemB.processData(dto);
    }
}

2. 抽象公共接口

如果MyClass包含业务行为,在公共模块定义抽象接口(比如IMyClass),让MyClass实现该接口,外观层返回接口类型,子系统B的方法参数使用接口而非具体类。

示例代码:

// 公共接口
public interface IMyClass {
    String getName();
    int getAge();
    void doBusiness();
}

// 子系统A内部类实现接口
public class MyClass implements IMyClass {
    private String name;
    private int age;

    @Override
    public String getName() { return name; }
    @Override
    public int getAge() { return age; }
    @Override
    public void doBusiness() {
        // 子系统A内部业务逻辑
        System.out.println("执行A内部业务");
    }
}

// 子系统A的外观类
public class SubsystemAFacade {
    public IMyClass createMyClass(String name, int age) {
        return new MyClass(name, age);
    }
}

// 子系统B的方法(依赖抽象接口)
public class SubsystemB {
    public void triggerBusiness(IMyClass myClass) {
        myClass.doBusiness();
        System.out.println("基于数据:" + myClass.getName() + "处理B逻辑");
    }
}

3. 完全封装业务逻辑

如果子系统B不需要直接操作MyClass的任何数据或行为,只是触发子系统A的某个业务流程,直接将该业务封装到外观方法中,子系统B仅调用外观方法,无需接触任何A的内部类型。

示例代码:

// 子系统A内部类
public class MyClass {
    private String name;
    private int age;

    public void executeInternalLogic() {
        // 子系统A内部业务逻辑
        System.out.println("执行A内部逻辑:" + name);
    }
}

// 子系统A的外观类
public class SubsystemAFacade {
    public void runBusiness(String name, int age) {
        MyClass myClass = new MyClass(name, age);
        myClass.executeInternalLogic();
        // 其他A内部流程
    }
}

// 子系统B的方法(直接调用外观)
public class SubsystemB {
    public void startProcess() {
        SubsystemAFacade facade = new SubsystemAFacade();
        facade.runBusiness("张三", 25);
    }
}

核心原则

无论哪种方案,核心都是让子系统B与子系统A的内部实现完全隔离:B只依赖公共的DTO、抽象接口或外观提供的方法,不直接引用A的任何内部类,这样才能真正降低耦合度,符合外观模式的设计目标。

内容的提问来源于stack exchange,提问作者Gilded Json

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 09:34:54