I have a class that I would like to present in two different ways: as an item that can be manipulated and configured by the user, and as an item that can only be displayed. In the example below I am using a shape that can be either drawn and changed, or just drawn.
Normally, to do this I would set up a base class (
Shape
) and two derived classes (
ConfigurableParallelogram
and
DisplayOnlyParallelogram
). I would usually only use interfaces as "contracts", so I would probably have an
IShape
interface to allow for different the abstractions of different shapes.
However, it occurred to me that interfaces are also "interfaces", like SQL Views, that should allow the same object to be viewed multiple ways. So I decided to try and set up an object hierarchy along those lines.
To begin with, I created my interfaces:
public interface IConfigurableShape
{
public int Size { get; set; }
public Brush Colour { get; set; }
public void Draw();
public IDisplayOnlyShape GetFinalVersion();
}
public interface IDisplayOnlyShape
{
public int Size { get; }
public Brush Colour { get; }
public string Name { get; }
public void Draw();
}
I then created a class that implements both interfaces.
public class Parallellogram : IConfigurableShape, IDisplayOnlyShape
{
private int _size;
private Brush _colour;
private string _name;
public Parallellogram()
{
_size = 1;
_colour = Brushes.Black;
}
public Parallellogram(Parallellogram predefinedShape)
{
CopyConfigFrom(predefinedShape);
}
#region IConfigurableShape member implementations
int IConfigurableShape.Size { get { return _size; } set { _size = value; } }
Brush IConfigurableShape.Colour
{
get { return _colour; }
set { _colour = value; }
}
IDisplayOnlyShape IConfigurableShape.GetFinalVersion()
{
_name = "use some name-determining logic here";
return new Parallellogram(this);
}
void IConfigurableShape.Draw()
{
}
#endregion
#region IDisplayOnlyShape member implementations
int IDisplayOnlyShape.Size { get { return _size; } }
Brush IDisplayOnlyShape.Colour { get { return _colour; } }
string IDisplayOnlyShape.Name { get { return _name; } }
void IDisplayOnlyShape.Draw()
{
}
#endregion
public void CopyConfigFrom(IDisplayOnlyShape providedShape)
{
_size = providedShape.Size;
_colour = providedShape.Colour;
_name = providedShape.Name;
}
}
My issue with this is that I have two constructors, each intended for the creation of different "views" of the object. But since constructors cannot be defined in the interfaces, I don't see a way to restrict the use of the two constructors. I would not want a display-only
Parallelogram
created with the first constructor since it would not ensure that the configuration of the object has been properly done (in this case, the
Name
property would not be set). But I don't see a way to prevent it.
Understandably, the code above could be easily changed to ensure that
Size
,
Colour
, and
Name
are always properly configured. It could also be easily refactored to use just one constructor. But this code is just a simplification for discussion purposes.
Is there a "standard" way to fix the multiple exposed constructors issue? Or is this whole example a gross anti-pattern that can only be handled by deleting the code, wiping my hard drive, and targeting my house with a tactical nuke?
What I have tried:
Looking up many online articles. However, all I have been able to find is discussions of inheriting multiple interfaces as a way of handling inheritance from multiple classes.