locked
Factory pattern and Nested interfaces RRS feed

  • Question

  • User197122282 posted

    I am trying to create a generic implementation of the factory pattern where all concrete classes are handled using a reference to the base interface. However, some classes may have special requirements. Let us see the following example:

    public interface ICurrencyBase
    {
        string sell();
        string buy();
    }

    The following concrete classes implement the above interface:

    public class ConcreteRupee : ICurrencyBase
    {
        public ConcreteRupee() {}
    
        public string buy()
        {    return "buy rupee";     }
    
        public string sell()
        {    return "sell rupee";    }
    }
    public class ConcreteDollar : ICurrencyBase
    {
        public ConcreteDollar() {}
    
        public string buy()
        {    return "buy dollar";    }
    
        public string sell()
        {    return "sell dollar";   }
    }

    However, I have another concrete class with an additional method requirement. For this I define an additional interface which implements the base interface. The concrete class then implements this new interface:

    public interface ISpecialCurrency : ICurrencyBase //inherit from the base interface
    {
        string convert ();
    }

    public class ConcreteSpecial : ISpecialCurrency //implement the new child interface {
        public ConcreteSpecial() { }
    
        public string buy()
        {
            return "buy special";
        }
    
        public string sell()
        {
            return "sell special";
        }
    
        public string convert() //new method added 
        { return "convert special"; } 
    }

    Then I have the factory class which creates objects of the concrete classes:

    public class CurrencyFactory
    {
        public CurrencyFactory() {}
    
        public static ICurrencyBase GetFactory (string type)
        {
            if (type == "Rupee")
                return new ConcreteRupee();
    
            if (type == "Dollar")
                return new ConcreteDollar();
    
            if (type == "Special")
                return new ConcreteSpecial();
    
            throw new Exception ("No such currency found");
        }
    }

    Using the currency factory above, I can now create instances of the concrete classes and have them referenced through ICurrencyBase. However, the problem is that ICurrencyBase cannot reference the convert() method defined through the child interface:

    //ICurrencyBase icurrencyBase = CurrencyFactory.GetFactory("Rupee");  
    //ICurrencyBase icurrencyBase = CurrencyFactory.GetFactory("Dollar");
    ICurrencyBase icurrencyBase = CurrencyFactory.GetFactory("Special");
    
    string buy  = icurrencyBase.buy  ();
    string sell = icurrencyBase.sell ();
    string deal = icurrencyBase.convert (); // Problem: ICurrencyBase CANNOT reference the convert() method

    How do I solve the above problem where we can use a reference of the base interface to handle requests to all concrete classes.

    Thanks.
     

     



     

    Thursday, May 2, 2013 1:35 AM

All replies

  • User1557244751 posted

    As you have inherited ICurrencyBase in ISpecialCurrency convert method won't be accessible through ICurrencyBase.

    I you want it should be accessible through ICurrencyBase then you need to reverse the inheritance as below.

    public interface ISpecialCurrency
    { 
        string Convert (); 
    }
    
    public interface ICurrencyBase : ISpecialCurrency
    { 
        string Buy(); 
        string Sell(); 
    }

    Thursday, May 2, 2013 1:55 AM
  • User197122282 posted

    Doesn't make sence to me. A reference to ISpecialCurrency can not reference Buy, Sell methods.

    The above example is in the context of Data Access Layer repository where I may have the following IDAL base interface.

    public interface IDAL
    {
         bool Save ();
         bool Update ();
         List<T> GetAll()
    }

    All concrete factories then implement this interface. For example, ProductDAL : IDAL ...,   EmployeeDAL: IDAL ...

    However, each object (Product, Employee) may have its own requirements. In this case, the base IDAL reference cannot handle all objects as shown above.

    Thursday, May 2, 2013 2:25 AM
  • User-816767241 posted

    I have (exactly!?) similar situation in one of my projects.

    Problem Description is: How to work with different types of derived objects (interfaces) returned as base interface reference from factory methods / abstract factories.

    I am forced to think around the solution like this:

    I am passing string as the type name based on which factory knows what to instantiate. [Assumption should be - I know what type-name to pass from some kind of documentation or shared knowledge of factory implementaiton]

    If so, then the type information (string form) should be preserved and available from the base interface - e.g. string getType(); or string getCurrencyType();

    Because I provide an information to the factory, I should be able to get it back also (I am not expecting a concrete class, just string name for later inspection on the base interface I received from factory - to do some special processing may be!!!!!!)

    Also, I should be aware of the string-names to interfaces mapping. [again through documentation of the factory implementation]

    Hence, I should know that an interface reference ICurrencyBase that returns "Special" as getType() or getCurrencyType() should cast to ISpecialCurrency nicely.

    Hence, I would cast it as:

    ICurrencyBase currency;
    
    if(currency.getType() == "Special" && currency is ISpecialCurrency)
    {
        // do work here
    }
    else
    {
        // I don't know!
    }


    Is there a better design idea? I also would like to know!

    Friday, May 17, 2013 9:27 AM
  • User459659623 posted

    I am trying to create a generic implementation of the factory pattern 
    where all concrete classes are handled using a reference to the base interface. However, some classes may have special requirements. Let us see the following example:
    public interface ICurrencyBase
    {
        string sell();
        string buy();
    }

    The following concrete classes implement the above interface:

    public class ConcreteRupee : ICurrencyBase { public ConcreteRupee() {} public string buy() { return "buy rupee"; } public string sell() { return "sell rupee"; } }
    public class ConcreteDollar : ICurrencyBase { public ConcreteDollar() {} public string buy() { return "buy dollar"; } public string sell() { return "sell dollar"; } }

    However, I have another concrete class with an additional method requirement. For this I define an additional interface which implements the base interface. The concrete class then implements this new interface:

    public interface ISpecialCurrency : ICurrencyBase //inherit from the base interface { string convert (); }

    public class ConcreteSpecial : ISpecialCurrency //implement the new child interface { public ConcreteSpecial() { } public string buy() { return "buy special"; } public string sell() { return "sell special"; } public string convert() //new method added  { return "convert special"; } }

    Then I have the factory class which creates objects of the concrete classes:

    public class CurrencyFactory { public CurrencyFactory() {} public static ICurrencyBase GetFactory (string type) { if (type == "Rupee") return new ConcreteRupee(); if (type == "Dollar") return new ConcreteDollar(); if (type == "Special") return new ConcreteSpecial(); throw new Exception ("No such currency found"); } }

    Using the currency factory above, I can now create instances of the concrete classes and have them referenced through ICurrencyBase. However, the problem is that ICurrencyBase cannot reference the convert() method defined through the child interface:

    //ICurrencyBase icurrencyBase = CurrencyFactory.GetFactory("Rupee");  //ICurrencyBase icurrencyBase = CurrencyFactory.GetFactory("Dollar"); ICurrencyBase icurrencyBase = CurrencyFactory.GetFactory("Special"); string buy = icurrencyBase.buy (); string sell = icurrencyBase.sell (); string deal = icurrencyBase.convert (); // Problem: ICurrencyBase CANNOT reference the convert() method

    How do I solve the above problem where we can use a reference of the base interface to handle requests to all concrete classes.

    Thanks.
     

     



     

    Please try below code


    public interface ICurrencyBase { string sell(); string buy(); string convert(); }
      public class ConcreteRupee : ICurrencyBase
            {
                public ConcreteRupee() { }
    
                public string buy()
                { return "buy rupee"; }
    
                public string sell()
                { return "sell rupee"; }
    
                public string convert()
                { return ""; }
            }

     public class ConcreteDollar : ICurrencyBase
            {
                public ConcreteDollar() { }
    
                public string buy()
                { return "buy rupee"; }
    
                public string sell()
                { return "sell rupee"; }
    
                public string convert()
                { return ""; }
            }
     public class ConcreteSpecial : ICurrencyBase
            {
                public ConcreteSpecial() { }
    
                public string buy()
                {
                    return "buy special";
                }
    
                public string sell()
                {
                    return "sell special";
                }
    
                public string convert() //new method added 
                { return "convert special"; }
            }
    public class CurrencyFactory
            {
                public CurrencyFactory() { }
    
                public static ICurrencyBase GetFactory(string type)
                {
                    if (type == "Rupee")
                        return new ConcreteRupee();
    
                    if (type == "Dollar")
                        return new ConcreteDollar();
    
                    if (type == "Special")
                        return new ConcreteSpecial();
    
                    throw new Exception("No such currency found");
                }
            }
    //ICurrencyBase icurrencyBase = CurrencyFactory.GetFactory("Rupee");  
    //ICurrencyBase icurrencyBase = CurrencyFactory.GetFactory("Dollar");
    ICurrencyBase icurrencyBase = CurrencyFactory.GetFactory("Special");
    
    string buy  = icurrencyBase.buy  ();
    string sell = icurrencyBase.sell ();
    string deal = icurrencyBase.convert ();







    Thursday, May 30, 2013 4:56 AM