Continue to Wednesday, January 28, 2015
-----------------------------------------------------
Interface Segregation Principle (ISP)
Interface Segregation Principle or ISP states that:
No client should be forced to depend on methods it does not use.
Many client-specific interfaces are better than one general-purpose interface.
What does that mean? Let's take an example. Suppose you are building an order processing system that accepts orders from the customers and places them in the system for dispatch and further processing. The orders can be accepted through various channels such as an ecommerce website, telephone and cash on delivery. To deal with this kind of processing you created the following abstract class:
public abstract class OrderProcessor
{
public abstract bool ValidatePaymentInfo();
public abstract bool ValidateShippingAddress();
public abstract void ProcessOrder();
}
The OrderProcessor class has three methods ValidatePaymentInfo(), ValidateShippingAddress() and ProcessOrder(). The ValidatePaymentInfo() method is supposed to validate the credit card information and return true if the information is correct. The ValidateShippingAddress() method is supposed to check whether the address is reachable by the available means of transport and if so return true. Finally, the ProcessOrder() will place an order into the system.
Now, assume that you created two concrete implementations of OrderProcessor as shown below:
public class OnlineOrder:OrderProcessor
{
public override bool ValidatePaymentInfo()
{
return true;
}
public override bool ValidateShippingAddress()
{
return true;
}
public override void ProcessOrder()
{
//place order here if everything is ok.
}
}
public class CashOnDeliveryOrder:OrderProcessor
{
public override bool ValidatePaymentInfo()
{
throw new NotImplementedException();
}
public override bool ValidateShippingAddress()
{
throw new NotImplementedException();
}
public override void ProcessOrder()
{
//place order here if everything is ok.
}
}
The OnlineOrder class is supposed to be used by some ecommerce application that accepts payments through credit cards. The CashOnDeliveryOrder class is supposed to serve cash on delivery orders. These orders won't accept any credit card payments. They accept only cash payments. Can you see the problem there? The two methods ValidatePaymentInfo() and ValidateShippingAddress() throw NotImplementedException because CashOnDeliverOrder doesn't need these methods. However, since the OrderProcessor class provides a general purpose interface the CashOnDeliveryOrder class is forced to write these methods. Thus ISP is being violated in this example.
Now let's fix the problem. The following code shows the corrected version of the classes:
public abstract class OrderProcessor
{
public abstract void ProcessOrder();
}
public abstract class OnlineOrderProcessor
{
public abstract bool ValidatePaymentInfo();
public abstract bool ValidateShippingAddress();
public abstract void ProcessOrder();
}
public class ECommerceOrder : OnlineOrderProcessor
{
public override bool ValidatePaymentInfo()
{
return true;
}
public override bool ValidateShippingAddress()
{
return true;
}
public override void ProcessOrder()
{
//place order here if everything is ok.
}
}
public class CashOnDeliveryOrder : OrderProcessor
{
public override void ProcessOrder()
{
//place order here if everything is ok.
}
}
The above code defines two abstract classes OrderProcessor and OnlineOrderProcessor. The OrderProcessor has only one method, ProcessOrder() whereas OnlineOrderProcessor has three methods - ValidatePaymentInfo(), ValidateShippingAddress() and ProcessOrder(). The ECommerceOrder class inherits from OnlineOrderProcessor and the CashOnDeliveryOrder class inherits from OrderProcessor. Since OrderProcessor doesn't contain the ValidatePaymentInfo() and ValidateShippingAddress() CashOnDelivery need not write them at all. Thus we created multiple client specific interfaces (OrderProcessor and OnlineOrderProcessor) instead of a generic one.
No comments:
Post a Comment