HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Code for simplifying the creation of Dimension Objects

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
theobjectsdimensionforsimplifyingcodecreation

Problem

I have a class that I use to represent a distance called Dimension.

Here is its four constructors:

/// 
    /// Accepts any valid architectural string value for input.
    /// 
    public Dimension(string passedArchitecturalString)
    {
         storeArchitecturalStringAsInternalUnit(passedArchitecturalString);
    }

    /// 
    /// Accepts standard types for input.
    /// 
    public Dimension(DimensionType passedDimensionType, double passedInput)
    {
        storeAsInternalUnit(passedDimensionType, passedInput);
    }

    /// 
    /// copy constructor - create a new Dimension with the same _intrinsicValue as the passed Dimension
    /// 
    public Dimension(Dimension passedDimension)
    {
        _intrinsicValue = passedDimension._intrinsicValue;
    }

    /// 
    /// Zero Constructor
    /// 
    public Dimension()
    {
        _intrinsicValue = 0;
    }


This question gives some more background on my Dimension Class.

Because it is a class that I use so often and it usually uses inches. I had to write out the one of the full constructors every time that I wanted to use it.

Dimension inchDimension = new Dimension(DimensionType.Inch, 14.1875);


This became a major pain when creating things like my 3 dimensional Point object:

Dimension xDimension = new Dimension(DimensionType.Millimeter, 0);
Dimension yDimension = new Dimension(DimensionType.Millimeter, 0);
Dimension zDimension = new Dimension(DimensionType.Millimeter, 0);

        Point p = new Point(xDimension, yDimension, zDimension);


So I created a class to generate these objects called DimensionGenerator.

```
public class DimensionGenerator
{

///
/// Default generator sets to inches
///
public DimensionGenerator()
{
_internalType = DimensionType.Inch;
}

///
/// This constructor allows you to specify a static type and change it later
///
/// DimensionType to use for now
public DimensionGenerator(DimensionType

Solution

The concept/pattern that you are trying to apply to DimensionGenerator is actually a factory.
You can approach this problem in two major ways, the factory which is what you were trying to do and by subclassing.

To make the factory pattern correct your dimension class must not have any public constructor and all instances shall be created by calling the factory method:

public class DimensionFactory
{
    public Dimension MakeInchDimension(double distance){
        return new Dimension(DimensionType.Millimeter, distance);
    }
    //more methods for other types
}


Should there be many of DimensionType that would be impractical to define a method for each type then you could do the factory like you already pretty much do.

public class DimensionFactory{
    private readonly DimensionType dimensionType;
    public DimensionFactory(DimensionType dimensionType){
        this.dimensionType = distance;
    }
    public Dimension MakeDimension(double distance){
        return new Dimension(dimensionType, distance);
    }  
}


In this approach you will end up with a factory object per each dimension type and you will have a generic Make method for all types, this is a big pro since all types are built in the same way. In the first approach you would have to change the interface if you wanted to add a new dimension type in this approach you don't have to do anything at all.

You could also sub class Dimension so you would have one class per DimensionType, once again this approach is only feasible if there are few DimesnionTypes. in this approach Dimension shall be abstract:

public InchDimension : Dimension{
     public InchDimension(double distance):base(DimensionType.Inch, distance){}
}


Edit
Asside from creating dimension your major concern was about comparing them. I'll assume that you can only compare objects of the same dimension and that you can convert any dimension to any other dimension. This way you are detaching conversion from comparison and comparison algorithm is solved easier.

public Dimension{ 
   public DimensionType DimensionType{get; private set;}
   public Dimension(DimensionType type, double value){
       DimensionType = type;
       Value = value;
   }
   public double Value{get; set;}
   public Dimension ConvertTo(DimensionType type){
      //if this dimension type is not consersible to type then throw NotSupportedException()
      //else do the convertion logic between this type and the other.
   }
}

public DimensionComparer : IEqualityComparer{
   public bool Equals(Dimension d1, Dimension d2){
       if(d1.DimensionType != d2.DimensionType){
           throw new NotSupportedException("cannot compare different dimmension types, please convert your dimension first");
       }
       return d1.Value == d2.Value;
   }
   public int GetHashCode(Dimension d){
      return d.Value ^ d.DimensionType.GetHashCode();
   }
}

Code Snippets

public class DimensionFactory
{
    public Dimension MakeInchDimension(double distance){
        return new Dimension(DimensionType.Millimeter, distance);
    }
    //more methods for other types
}
public class DimensionFactory{
    private readonly DimensionType dimensionType;
    public DimensionFactory(DimensionType dimensionType){
        this.dimensionType = distance;
    }
    public Dimension MakeDimension(double distance){
        return new Dimension(dimensionType, distance);
    }  
}
public InchDimension : Dimension{
     public InchDimension(double distance):base(DimensionType.Inch, distance){}
}
public Dimension{ 
   public DimensionType DimensionType{get; private set;}
   public Dimension(DimensionType type, double value){
       DimensionType = type;
       Value = value;
   }
   public double Value{get; set;}
   public Dimension ConvertTo(DimensionType type){
      //if this dimension type is not consersible to type then throw NotSupportedException()
      //else do the convertion logic between this type and the other.
   }
}

public DimensionComparer : IEqualityComparer<Dimension>{
   public bool Equals(Dimension d1, Dimension d2){
       if(d1.DimensionType != d2.DimensionType){
           throw new NotSupportedException("cannot compare different dimmension types, please convert your dimension first");
       }
       return d1.Value == d2.Value;
   }
   public int GetHashCode(Dimension d){
      return d.Value ^ d.DimensionType.GetHashCode();
   }
}

Context

StackExchange Code Review Q#56497, answer score: 2

Revisions (0)

No revisions yet.