Today we will talk about yet another Design Pattern. Imagine situation in which you have finally rented new building for your business. Not sure how it is in other countries, but I guess that for each enterprise you have to pass many verifications standardized by government. Those should verify if your building, and the conditions are good for people, who will work there. So in few recent months you have to accept many visitors, like electrician, plumber, office designer, etc. They all will diagnose and assessment your building going from floor to floor and from room to room. I hope you already have some class diagram in you mind. I have a question: who better knows logic for validating electricity entrance into building, and validating electricity in floor shields, also if all lamps are connected correctly in rooms? Of course Electrician – your next week visitor. He encapsulates logic of validating certain elements of you building.

 

VISITOR


Visitor – is Design Pattern, that allows you separate different sets of logic/algorithms from elements in your system, on which that logic/algorithms should be applied. It also allows you easily add and change that logic without impact on your existing system and that is the biggest benefit of using this DP as per me.
Lets talk around our example.
So the encapsulated logic lives within concrete Visitor. Logic can be applied to Elements in the system. Basically you have two interfaces which represent core of this design pattern – they are
IVisitor
public interface IVisitor 
{ 
    void Visit(OfficeBuilding building); 
    void Visit(Floor floor); 
    void Visit(Room room); 
}
IElement
public interface IElement 
{ 
    void Accept(IVisitor visitor); 
} 

ElectricitySystemValidator
One of the concretes of the IVisitor is ElectricitySystemValidator and it might look like in code snippet below. What does this class tells to us? It tells that some logic for each of the elements lives in one visitor and it is forced to provide that logic for all elements in your system, so you can easily pass electrician visitor from floor to floor and be sure that he know what he must do out there.
public class ElectricitySystemValidator : IVisitor 
{ 
    public void Visit(OfficeBuilding building) 
    { 
        var electricityState = (building.ElectricitySystemId > 1000) ? "Good" : "Bad"; 
        Console.WriteLine(string.Format("Main electric shield in building {0} is in {1} state.", building.BuildingName, electricityState)); 
    } 

    public void Visit(Floor floor) 
    { 
        Console.WriteLine(string.Format("Diagnosting electricity on floor {0}.", floor.FloorNumber)); 
    } 

    public void Visit(Room room) 
    { 
        Console.WriteLine(string.Format("Diagnosting electricity in room {0}.", room.RoomNumber)); 
    } 
}
PlumbingSystemValidator
Does quite similar work as ElectricitySystemValidator, but is takes into account building’s age to have an idea of the plumbing system state. Also it does nothing for rooms, since it is common, that you have no water in all rooms unless your building is special plant.
Elements
We have kind of traversing object structure. It starts with OfficeBuilding, it has Floors, any floor can have many rooms. Lets take quick look on Floor implementation.
Floor
public class Floor : IElement 
{ 
    private readonly IList<Room> _rooms = new List<Room>(); 
    public int FloorNumber { get; private set; } 
    public IEnumerable<Room> Rooms { get { return _rooms; } } 

    public Floor(int floorNumber) 
    { 
        FloorNumber = floorNumber; 
    } 

    public void AddRoom(Room room) 
    { 
        _rooms.Add(room); 
    } 

    public void Accept(IVisitor visitor) 
    { 
        visitor.Visit(this); 
        foreach (var room in Rooms) 
        { 
            room.Accept(visitor); 
        } 
    } 
} 
As you see above Accept method, that accepts visitor them passes it to its inner structure and visitor will know how to deal with those elements. So in future if you will have to change how the electrician should behave in room, you can be sure that logic will be moved to the room smoothly without need to change Floor class.
OfficeBuiling is quite similar, but is has additional properties. Room is very simple since doesn’t aggregate or compose other elements.

Source code elements in diagram

You can take a look on the picture below to see other pieces of my demo program.


Nothing so much special till now? Then let see usage and output of my super demo example.

Usage

var floor1 = new Floor(1); 
floor1.AddRoom(new Room(100)); 
floor1.AddRoom(new Room(101)); 
floor1.AddRoom(new Room(102)); 
var floor2 = new Floor(2); 
floor2.AddRoom(new Room(200)); 
floor2.AddRoom(new Room(201)); 
floor2.AddRoom(new Room(202)); 
var myFirmOffice = new OfficeBuilding("[Design Patterns Center]", 25, 990); 
myFirmOffice.AddFloor(floor1); 
myFirmOffice.AddFloor(floor2); 

var electrician = new ElectricitySystemValidator(); 
myFirmOffice.Accept(electrician); 

var plumber = new PlumbingSystemValidator(); 
myFirmOffice.Accept(plumber);
Output:

Main electric shield in building [Design Patterns Center] is in Bad state.

Diagnosting electricity on floor 1.

Diagnosting electricity in room 100.

Diagnosting electricity in room 101.

Diagnosting electricity in room 102.

Diagnosting electricity on floor 2.

Diagnosting electricity in room 200.

Diagnosting electricity in room 201.

Diagnosting electricity in room 202.

Plumbing state of building [Design Patterns Center] probably is in Good condition, since builing is New.

Diagnosting plumbing on floor 1.

Diagnosting plumbing on floor 2.

Classic UML diagram

So the general UML diagram for this Design Pattern looks like on the image below:
Visitor1[1]
I hate that I have to go to bed, I still have a lot to add to this Design Pattern, since I see it very useful and thrilling.

My Design Patterns Table

If you haven't subsribed yet, you can subsribe below: