Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Design pattern for private members access?

Tags:

c#

oop

Let's use this simple example :

Connect4Board.cs :

public class Connect4Board
{
    private Box[,] _boxes = new Box[7, 6];

    public void DropPieceAt(int column, bool redPiece)
    {
        //Safe modifications to box colors.
    }        

    public Box GetBoxAt(int x, int y)
    {
        return _boxes[x, y];
    }
}

Box.cs :

public class Box
{
    public bool IsRed { get; private set; }
    public bool IsEmpty { get; private set; }
}

I want GetBoxAt() to return a box with read-only properties. However I want my Connect4Board to be able to change boxes colors.

Let's assume that I don't want to use internal modifier at all.

My solution (quite ugly) :

public class Connect4Board
{
    private Box.MutableBox[,] _mutableBoxes = new Box.MutableBox[7, 6];

    public Connect4Board()
    {
        for (int y = 0; y < 6; y++)
        {
            for (int x = 0; x < 7; x++)
            {
                _mutableBoxes[x, y] = new Box.MutableBox();
            }
        }
    }

    public void DropPieceAt(int column, bool isRed)
    {
        //Safe modifications to box colors.
    }        

    public Box GetBoxAt(int x, int y)
    {
        return _mutableBoxes[x, y].Box;
    }
}

public class Box
{
    public bool IsRed { get; private set; }
    public bool IsEmpty { get; private set; }

    private Box()
    {
    }

    public class MutableBox
    {
        public Box Box { get; private set; }

        public MutableBox()
        {
            Box = new Box();
        }

        public void MakeRed() { //I can modify Box here }

        public void MakeYellow() { //I can modify Box here }

        public void MakeEmpty() { //I can modify Box here }
    }
}

Is there a good design pattern to make this more elegant ?

like image 933
Simon V. Avatar asked Jan 14 '23 10:01

Simon V.


2 Answers

There are a number of strategies you could use.

It's often useful to program to interfaces. The IBox interface below would not allow people to edit the box (without casting it to a Box), but still leaves your code simple.

public class Connect4Board
{
    private Box[,] _boxes = new Box[7, 6];

    public void DropPieceAt(int column, bool redPiece)
    {
        //Safe modifications to box colors.
    }        

    public IBox GetBoxAt(int x, int y)
    {
        return _boxes[x, y];
    }
}

public interface IBox
{
    bool IsRed { get; }
    bool IsEmpty { get; }
}

public class Box : IBox
{
    public bool IsRed { get; set; }
    public bool IsEmpty { get; set; }
}

Another approach would be to make boxes always immutable (like strings), and instead of modifying the states of your boxes, you just modify which box is in which location in your array:

public class Connect4Board
{
    private Box[,] _boxes = new Box[7, 6];

    public Connect4Board()
    {
        for(int i = 0; i<7; i++)
        {
            for(int j = 0; j<6; j++)
            {
                // Notice how you're not changing a color, but assigning the location
                _boxes[i,j] = Box.Empty;
            }
        }
    }

    public void DropPieceAt(int column, bool redPiece)
    {
        // Modifications to the top empty location in the given column.
    }        

    public Box GetBoxAt(int x, int y)
    {
        return _boxes[x, y];
    }
}

public class Box
{
    public bool IsRed { get; private set; }
    public bool IsBlack { get; private set; }
    public bool IsEmpty { get; private set; }

    private Box() {}

    public static readonly Box Red = new Box{IsRed = true};
    public static readonly Box Black = new Box{IsBlack = true};
    public static readonly Box Empty = new Box{IsEmpty = true};
}
like image 164
StriplingWarrior Avatar answered Jan 17 '23 06:01

StriplingWarrior


WOuld this work for you? Make Box Immutable, with static factory, and add static properties that return new boxes with various colors

  public class Box
  {
       private Box() {}
       private Box(Color color) { Color = color; }
       public static Box Make(Color color) { return new Box(color); }
       public static Box RedBox { get { return new Box(Color.Red); } }
       public static Box GreenBox { get { return new Box(Color.Green); } }
       public static Box BlueBox { get { return new Box(Color.Blue); } }
       //   ... etc.
   }
like image 33
Charles Bretana Avatar answered Jan 17 '23 06:01

Charles Bretana