首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在调用代码中依赖于数据时,如何解耦实现细节

在调用代码中依赖于数据时,如何解耦实现细节
EN

Stack Overflow用户
提问于 2018-06-06 15:50:32
回答 1查看 416关注 0票数 0

如果实现效果必须依赖于调用代码中的某些参数,如何将接口实现与调用代码分离?

这听起来可能很费解,所以这里是一个真实的例子:

  • 一些网上商店销售不同品牌的产品;
  • 在用户购买过程中,我们需要根据购买产品的品牌向不同的仓库提交数据;
  • 所有这些存储都可以通过相同接口的相同实现访问,但可以通过不同的底层连接访问。

遵循IoC原则,我们应该有一个按顺序处理代码的存储接口实现的实例,而不知道它的内部结构。然而,必须根据产品的品牌将数据发送到不同的服务器,这意味着我们必须以某种方式影响该实现。

如果我们将任何数据(品牌数据或存储库连接配置)传递给存储库,我们要么将存储库接口耦合到品牌实体,要么将订单处理代码传递到存储库实现细节。

那么如何按照IoC原则来实现这个场景呢?其他脱钩模式的建议也受到欢迎。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-17 11:24:49

我得出的结论是,在这种情况下,代码不能完全解除耦合。通过对手头任务的定义,业务逻辑和存储库实现之间存在着耦合。

然而,为了进一步简化代码维护,我最终使用了以下体系结构(伪代码):

核心接口:

代码语言:javascript
运行
复制
// Main repository interface
interface OrdersRepositoryInterface {
    store(order: Order): bool;

    // …other methods
}

// An interface of a factory that will be used to create repository instances with different configurations (different underlying storages, for example)
interface OrdersRepositoryFactoryInterface {
    createRepository(configuration: OrdersRepositoryConfigurationInterface): OrdersRepositoryInterface;
}

// An interface of a container that will create different instances of repositories based on specified brand
// An implementation of this interface is the coupling point between business logic and data persistence logic
interface OrdersRepositoryContainerInterface {
    get(brand: Brand): OrdersRepositoryInterface;
}

存储库工厂实现(与存储库本身紧密耦合,如果在接口本身中指定了存储库构造函数,则可以避免,但我个人认为这是不好的做法):

代码语言:javascript
运行
复制
class OrdersRepositoryImplementation implements OrdersRepositoryInterface {
    constructor(configuration: OrdersRepositoryConfigurationInterface) {
        // …
    }

    store(order: Order): bool {
        // …
    }
}

class OrdersRepositoryFactory implements OrdersRepositoryFactoryInterface {
    createRepository(configuration: OrdersRepositoryConfigurationInterface): OrdersRepositoryInterface {
        return new OrdersRepositoryImplementation(configuration);
    }
}

存储库容器实现:

代码语言:javascript
运行
复制
class OrdersRepositoryContainer implements OrdersRepositoryContainerInterface {
    get(brand: Brand): OrdersRepositoryInterface {
        var factory = IoC.resolve(OrdersRepositoryFactoryInterface);

        var configuration1 = …;
        var configuration2 = …;

        if (brand.slug === "brand1") {
            return factory.createRepository(configuration1);
        } else {
            return factory.createRepository(configuration2);
        }
    }
}

IoC-容器绑定(如果容器支持它,那么最好是绑定类而不是实例,因为在这些实现的构造函数中可以使用自动依赖注入):

代码语言:javascript
运行
复制
IoC.bindInstance(OrdersRepositoryFactoryInterface, new OrdersRepositoryFactory());
IoC.bindInstance(OrdersRepositoryContainerInterface, new OrdersRepositoryContainer());

最后,但并非最不重要的是,订单处理代码:

代码语言:javascript
运行
复制
var order = …;

var repositoryContainer = IoC.resolve(OrdersRepositoryContainerInterface);

var repository = repositoryContainer.get(order.brand);

repository.store(order);

该体系结构将允许轻松替换存储库解析逻辑。例如,将来可能会统一所有品牌的存储库,在这种情况下只能替换OrderRepositoryContainerInterface实现。但是,OrdersRepositoryContainer仍然与存储库的实现相耦合,因为它必须知道如何以及在何处获得它们的配置。

我会把这个答案标为已被接受,但如果有人提出更好的主意,我会欣然改变的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50724596

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档