I am attempting to write an extensible graphing calculator program, in which individual components can be extended or replaced as needed without changing other components. I create a DLL containing all of the classes, and a simple program that implements the contained controls/types (just runs a winforms Form containing a control contained in the DLL). This way, someone can either add an extension DLL to the Calculator program itself, or just reference the DLL and work directly with components and still be able to replace/extend them.
I understand that each class consuming a replaceable/extendible component should operate only only the abstract base class / interface contracts. I provide a default implementation of each of the contracts and they are created in a static Create() method in the base class (sometimes with parameters, usually not for controls and the like).
Currently, the Create() method just returns a new instance of the default class implementation. I was considering two ways of implementing the factory method:
Use a static class like CalculatorSettings that internally stores the default types/instances to return, in which loading extensions or calling specific methods on the CalculatorSettings class can change these stored types so that Create() methods are updated automatically. For example, inside the Create() method, a line like
return CS.DefaultEquation;
However, this means that each class becomes aware of this particular class.Store an internal static delegate in each of the abstract base classes that is invoked when Create() is called, passing any parameters if present. This delegate would default to returning a new instance of the default class. Since it is internal, a static CalcualtorSettings class could change the delegate without the target abstract base class having to be aware of the CalculatorSettings class. No one would be able to change the delegate without going through the CalculatorSettings class, unless using reflection or something.
My question is, are there any other downsides to using these particular methods? Are there any alternatives that might be better?
Example of situation: EquationBox abstract base class, provides contracts for obtaining an equation, no matter the form of the GUI controls used to obtain it. The Create() method would return the stored type or invoke a delegate to return the DefaultEquationBox class. This class also uses another abstract base class, the ConstantBox, which in turn returns a DefaultConstantBox on calling Create(). The EquationBox instances themselves are contained in an EquationBoxContainer abstract base class that holds an IEnumerable of EquationBox classes and a contract to return an IEnumerable of Equations and such.
In this case, you could replace the container without changing the EquationBoxes, replace the ConstantBox type without replacing the EquationBox, or extend any of these default types and have it automatically update the base class Create() method to return the new types.