Asked by:
Factory pattern and Nested interfaces

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.
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