4

我对编程相当陌生,我很难理解如何有效地应用以下链接(ATM 链接)中显示的原则:

http://www.objectmentor.com/resources/articles/isp.pdf

基本上,它从不抱怨 ISP(接口隔离原则)的设计开始,然后继续将行为重构为不同的接口。

我的问题是:我们不使用接口来表达不那么(或不)相关的抽象之间的共同行为吗?

将方法封装在接口中的意义何在,即使没有一个方法与将要实现它们的类共享?在哪种情况下这可能被认为是有用的?

如果我们继续该示例的行,则给出以下代码:

public interface ITransaction
{
    void Execute();
}

public interface IDepositUi
{
    void RequestDepositAmount();
}

public class DepositTransaction : ITransaction
{
    private IDepositUi depositUI;

    public DepositTransaction(IDepositUi ui)
    {
        depositUI = ui;
    }

    public virtual void Execute()
    {
        /*code*/
        depositUI.RequestDepositAmount();
        /*code*/
    }
}

public interface WithdrawalUI
{
    void RequestWithdrawalAmount();
}

public class WithdrawalTransaction : ITransaction
{
    private WithdrawalUI withdrawalUI;

    public WithdrawalTransaction(WithdrawalUI ui)
    {
        withdrawalUI = ui;
    }

    public virtual void Execute()
    {
        /*code*/
        withdrawalUI.RequestWithdrawalAmount(); /*code*/
    }
}

public interface TransferUI
{
    void RequestTransferAmount();
}

public class TransferTransaction : ITransaction
{
    private TransferUI transferUI;

    public TransferTransaction(TransferUI ui)
    {
        transferUI = ui;
    }

    public virtual void Execute()
    {
        /*code*/
        transferUI.RequestTransferAmount();
        /*code*/
    }
}

public interface UI : IDepositUi, WithdrawalUI, TransferUI
{
}

据我了解,为了使用以前的设计,我们应该有类似的东西:

UI impui = new IMPLEMENTATIONUI(); // Some UI implementation
DepositTransaction dt = new DepositTransaction(Gui);
dt.Execute();

现在,我们不需要 IMPLEMENTATIONUI 实现每一个方法吗?如果是这样,它不会破坏 SRP 吗?

4

2 回答 2

1

难道我们不使用接口来表达不那么(或不)相关的抽象之间的共同行为吗?

是的,在 SOLID 中,需要接口来表达常见行为。你的 Transaction 接口就是一个很好的例子。DepositTransaction 和 WithdrawlTransaction 类都依赖于它。ISP(接口隔离原则)希望您将其拆分出来,因为您可能需要将 Transaction 对象传递给函数来执行它。所有的 SOLID 原则都是设计的,例如:

void ExecuteTransaction(Transaction transaction)
{
    transaction.Execute();
}

请注意,此方法只依赖于 Transaction 接口。这是依赖倒置。

如果您不创建此接口,则需要创建两种不同的方法来执行 WithdrawlTransaction 或 DepositTransaction;相反,您可以使用 ExecuteTransaction 方法并传入任何实现 Transaction 的内容。

ExecuteTransation(withdrawl_TransactionObject);

或者

ExecuteTransaction(deposit_TransactionObject);

或以后:

ExecuteTransaction(unanticipatedNewTypeOf_TransactionObject);

现在,我们不需要 IMPLEMENTATIONUI 实现每一个方法吗?如果是这样,它不会破坏 SRP 吗?

实现 UI 可能是用户用来与软件交互的东西。用户不会有单一职责,理论上他/她必须使用 IMPLEMENTATIONUI 类所需的所有接口。

我怀疑实现 UI 会实现所有接口,但它可能会使用所有这些接口来执行事务。套用“鲍勃叔叔”坚实的原则,您的用户界面应该充满易失性代码,而您的界面应该是最不易变的。

于 2017-04-07T13:54:27.213 回答
0

让一个接口从其他三个接口继承是否违反 ISP?

public interface UI : IDepositUi, WithdrawalUI, TransferUI
{
}

答案是我们无法判断。这取决于客户端是否依赖于整个接口。如果是这样,那么这不是 ISP 违规。如果客户端不依赖于所有三个继承的接口,那么这就是违规,客户端应该只依赖于它确实需要的任何接口。

正如您所观察到的,它可能违反了其他一些原则,但这超出了讨论 ISP 的范围。但我认为重点不在于您应该创建该组合界面。关键是您可以同时保留较小的隔离接口。

我们可能很想在巨型接口和一个巨型类上创建,因为一个客户端依赖于所有三个接口。但如果我们这样做,另一个只需要提款或转账的客户将被迫依赖它不需要的更大的接口。

在现实生活中,这种事情变得失控,因为有人开始使用广泛的、模糊命名的界面,比如ITransactionService在你知道它之前,更多的开发人员把厨房水槽扔进去了。在示例中,接口被更具体地命名。这不会强制将它们隔离,但它会有所帮助。预先给他们这样的特定名称可以传达他们应该或不应该在其中的内容。它建议开发人员预先计划保持接口隔离。

于 2019-01-02T20:42:59.227 回答