c#interface segregation原理示例混淆

时间:2014-02-09 16:11:55

标签: c# oop solid-principles ooad interface-segregation-principle

我对编程很新,而且我很难理解如何有效地应用以下链接中显示的原理(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?。

2 个答案:

答案 0 :(得分:1)

我们是否使用接口来表达不相关(或不相关)抽象中的常见行为?

是的,在SOLID中,接口需要表达共同的行为。您的交易界面就是一个极好的例子。 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会实现所有接口,但是为了执行事务,它可能使用所有这些接口。用来解释"鲍勃叔叔" Solid Principles您的用户界面应该充满了易失性代码,而您的界面应该是非易失性的。

答案 1 :(得分:0)

拥有一个接口是否从另外三个接口继承了ISP违规?

public interface UI : IDepositUi, WithdrawalUI, TransferUI
{
}

答案是我们无法分辨。这取决于客户端是否依赖于整个接口。如果确实如此,则这不是ISP违规。如果客户端不依赖于所有三个继承的接口,则这是违规行为,客户端应仅依赖它需要的任何接口。

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

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

在现实生活中,这种事情变得失控了,因为有人开始使用诸如ITransactionService之类的宽泛,命名模糊的界面,并且在您不知道它的情况下,更多的开发人员将厨房的水槽投入了其中。在示例中,接口被更具体地命名。这不会强制将它们隔离开来,但是会有所帮助。预先给他们这样的特定名称,就可以传达其中应该包含或不应该包含的内容。它建议开发人员提前计划以保持界面隔离。