How can I make sure that I am implementing the Open / Closed principle?

Let's say I have a base class called Shape, and I want each shape to be able to return its own region. I could make an Shapeinterface or an abstract class (and possibly other ways), but the end result is that each form will have a function called Area.

So, let's say I have a collection like:

List<Shape> bag = loadShapesFromXML(...)

And if I want to add all areas together, I could do:

int total=0;
foreach (var s in bag)
   total += s.Area();

This follows an open / closed principle. I have a problem loadShapesFromXML. Suppose my XML looks like this:

<bag>
  <circle id="1" radius="5" />
  <square id="2" length="3" />
  <rectangle id="3" length="6" width="7"/>
</bag>

loadShapesFromXML "", , . , , //, , , ?

+4
3

, ReadFromXXXX WriteToXXXX. , , - .

"mapper" Xml - , node name:

  var creatorsMap = new Dictionary<string, Func<XElement, Shape>>
     {{"rectangle", node => new Rectangle(node.Element(....) ...)}};
  ...
  shapes.Add(creatorsMap[node.Name](node));

, , - , . , / .

+2

, , . XML .

<bag>
  <circle id="1" radius="5">Circle 1</circle> />
  <square id="2" length="3">Square 1</square> />
  <rectangle id="3" length="6" width="7">Rectangle 1</rectangle>/>
</bag>

. , . - XElement, "".

public abstract class shape
{
    private readonly string _ID;
    public string id
    {
        get
        {
            return _ID;
        }
    }

    public string Name { get; set; }

    public shape(string id, string name)
    {
        _ID = id;
        this.Name = name;
    }

    public shape(XElement element)
    {
        _ID = element.Attribute("id").Value;
        this.Name = element.Value;
    }

    public abstract XElement GetXElement();

    public abstract double Area();

}

. , (). , GetXElement XML node, XML.

public class circle : shape
{
    public int Radius { get; set; }

    public circle(string id, string name, int radius)
        : base(id, name)
    {
        this.Radius = radius;
    }

    public circle(XElement element)
        : base(element)
    {
        this.Radius = int.Parse(element.Attribute("radius").Value);
    }

    public override XElement GetXElement()
    {
        return new XElement("circle", new XAttribute("id", this.id), new XAttribute("radius", this.Radius), this.Name);
    }

    public override double Area()
    {
        return Math.PI * Radius * Radius;
    }
}

, , Open/Closed. , XML , Console.WriteLine(element) XML . , , , XML .

    public void TestMethod1()
    {
        var doc = XDocument.Load(xmlFile);
        double area=0;
        foreach (var shapeItem in doc.Descendants("bag").Descendants())
        {
            var type = Type.GetType("StackOverflowShapes." + shapeItem.Name + ",StackOverflowShapes");
            var myShape = (shape)Activator.CreateInstance(type, shapeItem);
            area += myShape.Area();
            var element = myShape.GetXElement();
            Console.WriteLine(element);
        }

        Assert.Equal(129.5398, area, 4);
    }

. , XML XML.

+1

-, , , loadShapesFromXML , , Shape , , .

class Shape
  var radius;
  var length;
  var width;
  var diagonal; //new ways of defining a shape would go here
  var id;
  var name;

- , Shape loadShapesFromXML. Shape, , , (, ..).

if(id == 1)
  bag.add(new Circle(this));
else if(id == 2)
  bag.add(new Square(this));
...
0

Source: https://habr.com/ru/post/1544399/


All Articles