Design Patterns

My book on design patterns is released

February 15, 2012 Book Reviews, Design Patterns, Success 23 comments

Dear Reader,

I’m glad to let you know, that I released my short free e-book on design patterns.

BookCover_480

It is available on web site http://designpatterns.andriybuday.com/

As you many know early 2010 I started writing series of blog post dedicated to GoF design patterns. I tried to keep my examples of patterns very simple and in the way, that person reading example can build associations with real or close to real world situations. I also translated all of the examples into Ukrainian and then decided to assemble small e-book. And now it is available for you.

Here is some introduction in Ukrainian (I’m not translating it to English, since if you cannot read in Ukrainian there is no point).

Опис
Книга «Дизайн патерни — просто, як двері» є безплатною україномовною книгою, що містить унікальні приклади до шаблонів проектування. Завдяки своїй нестандартній подачі матеріалу вона дозволить вам легко опанувати основи розуміння дизайн патернів чи систематично і дуже швидко повторити їх перед інтерв’ю. Спосіб написання книги дозволить провести час, відведений на її прочитання, без нудьги, а подекуди навіть захоплююче.
Освіжіть у своїй пам’яті призабуті дизайн патерни!

Завантажити книгу

У декількох словах
Книгу я написав із добрими намірами. Їх у мене було декілька. Я хотів упевнитися, що сам розумію усі класичні дизайн патерни. Ресурсів для цього є досить багато, але я вирішив реалізувати ці патерни самостійно та придумати власні приклади. Таким чином, починаючи із 16 січня 2010 я писав блог пости, які так чи інакше викликали зацікавлення в читачів. Щоб цей внесок в програмування був більш чітким, в мене виникло бажання випустити невеличку книжку, яка стала б колекцією цих блог постів.

Завітайте на сайт книги: http://designpatterns.andriybuday.com/
Та не забудьте подякувати автору, поширивши посилання.


23 comments


Help me select UML for book: hand-drawn or tool-prepared

October 14, 2011 Design Patterns 16 comments

As you may know I’m working on Design Patterns book in Ukrainian and as most of the posts I had on patterns have UML-s, I’m considering having UML diagrams in book as well to be consistent. Thus I can either prepare them in some UML tool or just draw. See yourself.

Drawn by me

FACTORY_NEW

Also drawn by me, but in advanced tool

image

And here how it looks like when on paper

image

image

Why I like hand-drawn option

I would like to use hand-drawn variant because it will make the book look cheery and will make the difference. It might bring some interest like “So what’s is really on that diagram?”. Also I still don’t position book as an “official” book, so I would like to have some bits of unofficially. Especially taking into account that auditory is mostly young starting developers.

Why I don’t like it

I’m of course hesitating, as this variant in its origin is inaccurate (of course I can try harder). Also maintaining such diagrams is bit more difficult, but I don’t see any problem with this.

Please help me choose!

 

[Added later (wasn’t in original post)]

After I posted this friend suggested me to use this online uml generation tool. And it would be great another option to consider, but it generates not really what I want:

image

But it was extremely nice, that to generate picture above I just used this code:

# Abstract Factory
[Cat]^[WoodenCat], [Cat]^[TeddyCat]
[Bear]^[WoodenBear], [Bear]^[TeddyBear]
[IToyFactory]^[WoodenToysFactory], [IToyFactory]^[TeddyToysFactory]
[TeddyToysFactory]uses-.->[TeddyBear]
[TeddyToysFactory]uses-.->[TeddyCat]
[Client]->[IToyFactory]
[Client]->[Cat]
[Client]->[Bear]
[WoodenToysFactory]uses-.->[WoodenCat]
[WoodenToysFactory]uses-.->[WoodenBear]

Nice tool, indeed, but for extremely simple diagrams.

[Added later (15 Oct, after comments)]

After comment by Satomi Joba I tried community edition of another tool, called Astah. Below is what I was able to draw by it. Two things about it: 1) Drawing in this tool is just fabulous, smooth and easy. For me it was more quick and intuitive drawing than in such matured tools as Enterprise Architect for example. 2) Although I’m not sure I like this bold borders and I wasn’t able to quickly change styling of diagram (maybe because of edition I used?).

image

Anyway question is still the same: do I use hand-drawing or do I use tool?


16 comments


Interpreter

May 30, 2011 Design Patterns 4 comments

Some imaginary company has very funny business, when people have garage sales, they go and buy everything they can fit into few of their trucks. In the end of the day they are very interested to know how much goods inside of each of the trucks cost. We don’t really care what they do after. But we are interested in knowing how they calculate cost of goods. Many things they buy are packed into packages, sometimes they put similar goods into one package, sometimes they double-triple pack fragile things. So company deals with trucks stuffed with packages of goods. The other day truck’s guts can hit different cost number. In the context of current date prices, having graph of packages/goods we can calculate total cost, this can be done by man, but company goes different way, trucks do it automatically. Each truck accumulates cost of each package, each package calculates cost of what’s inside (packages/goods), any stuff knows its today’s price.
INTERPRETER
Interpreter is design pattern that allows to represent language grammar and knows how to evaluate its sentences into parts that can be understood.
Talking about our dummy example, language would be truck/packages/goods, its current sentence would be stuffed truck ‘cause it has graph of language parts, and the meaning of the sentence would be total cost of the goods inside.
There are two kinds of expressions in the language, those that can be understood immediately, called terminal expressions, and those that require language logic to be applied to be understood, called nonterminal expressions.
Talking about our example, terminal expression would be old TV, Laptop or Bed, since we know that today old TV costs 100, Laptop 500 and Bed 400, and nonterminal expression would be package in which they put 3 laptops, where we have to apply logic to understand what it means to us.
Let’s take a look at our example source code:
Here are expressions our language contains:
    // Abstract expression
    public abstract class Goods
    {
        public abstract int Interpret(CurrentPricesContext context);
    }

    // Nonterminal expression
    public class GoodsPackage : Goods
    {
        public List<Goods> GoodsInside { get; set; }

        public override int Interpret(CurrentPricesContext context)
        {
            var totalSum = 0;
            foreach (var goods in GoodsInside)
            {
                totalSum += goods.Interpret(context);
            }
            return totalSum;
        }
    }

    // Terminal expression
    internal class TV : Goods
    {
        public override int Interpret(CurrentPricesContext context)
        {
            int price = context.GetPrice("TV");
            Console.WriteLine("TV: {0}", price);
            return price;
        }
    }

    // Here other terminal expressions go (Laptop, Bed)
As you can see GoodsPackage knows that for to be understood it has to accumulate cost of each things inside. In our example we have very simple language with only one rule for it, but in more complex languages we will have something different, like for math it could be (“+”, “-”, “/”, “*”, “Sqrt”, “Integral”, and so on…). Math would also have variety of terminal expressions, like numbers or variables, value of which can be substituted.
Two more things are left. It is context, which represent information global to the whole process, in our example prices as of today, and it is client, which actually somehow gets sentence and invokes method Interpret in order to understand sentence. Here below is only Client, I do not show CurrentPricesContext, since it would bring only noise to this example.
        public void RunInterpreterDemo()
        {
            // create syntax tree that represents sentence
            var truckWithGoods = PrepareTruckWithGoods();
            // get latest context
            var pricesContext = GetRecentPricesContext();
            // invoke Interpret
            var totalPriceForGoods = truckWithGoods.Interpret(pricesContext);

            Console.WriteLine("Total: {0}", totalPriceForGoods);
        }

        private CurrentPricesContext GetRecentPricesContext()
        {
            var pricesContext = new CurrentPricesContext();
            pricesContext.SetPrice("Bed", 400);
            pricesContext.SetPrice("TV", 100);
            pricesContext.SetPrice("Laptop", 500);
            return pricesContext;
        }

        public GoodsPackage PrepareTruckWithGoods()
        {
            var truck = new GoodsPackage() { GoodsInside = new List<Goods>() };

            var bed = new Bed();
            var doubleTriplePackedBed = new GoodsPackage() { GoodsInside = new List<Goods>() { new GoodsPackage() { GoodsInside = new List<Goods>() { bed } } } };
            truck.GoodsInside.Add(doubleTriplePackedBed);
            truck.GoodsInside.Add(new TV());
            truck.GoodsInside.Add(new TV());
            truck.GoodsInside.Add(new GoodsPackage() { GoodsInside = new List<Goods>() { new Laptop(), new Laptop(), new Laptop() } });

            return truck;
        }

Quickly output:
Bed: 400

TV: 100

TV: 100

Laptop: 500

Laptop: 500

Laptop: 500

Total: 2100

Interpreter is one of the design patterns that you most likely will never use in your life. It is bit cumbersome and has very specific application.

My Design Patterns Table


4 comments


Proxy

May 8, 2011 Design Patterns No comments

Taken from here: http://news.malaysia.msn.com/photogallery.aspx?cp-documentid=4417270&page=7Do you imagine yourself defusing bomb? Scary? Even if you couldn’t imagine this there is such profession as bomb defuser and people owning it are human as well, so I bet they feel scary when near bomb. For our luck there is technology nowadays that allows remotely operate with some kind of robot that can defuse bomb. Using robots also allows to do more complex operations with safely lifting bombs, and manipulating them. I bet human hands would shake while holding bomb, not robot’s.

Connection with robot is wireless of course and you would have special suit that makes you body operate robot remotely as you were it. (Ok on the picture above you see not such advance robot, but lets imagine we are in future.) Robot still has control panel on it that will allow operating it directly. This is needed just in case connection could not be made (say someone is blocking signal).

To summarize, robot is heavy instance and it can be operated directly or you can proxy your requests through special suit.

PROXY

Proxy is design pattern that surrogates real object and proxies requests to it when needed, it also instantiates real object if it is not yet instantiated.

Talking about example above, object which we use is robot (RobotBombDefuser) it is heavy stuff, which we move using remote controls aka. proxy suit (RobotBombDefuserProxy). As this suit works wirelessly with robot it knows how to connect to real object and how to pass your requests to it. The same is happening when we connect to some remote web server and call methods on it.

Proxy is also often used when you need lazy initialization. In this case instead of connecting to remote resource there is simple check if object is not null and then assigning an instance if needed.

Let’s see what we have in our example. Here is robot itself.

    public class RobotBombDefuser
    {
        private Random _random = new Random();
        private int _robotConfiguredWavelength = 41;
        private bool _isConnected = false;

        public void ConnectWireless(int communicationWaveLength)
        {
            if(communicationWaveLength == _robotConfiguredWavelength)
            {
                _isConnected = IsConnectedImmitatingConnectivitiyIssues();
            }
        }
        public bool IsConnected()
        {
            _isConnected = IsConnectedImmitatingConnectivitiyIssues();
            return _isConnected;
        }
        private bool IsConnectedImmitatingConnectivitiyIssues()
        {
            return _random.Next(0, 10) < 4; // immitates 40% good connection, aka. very bad
        }

        public virtual void WalkStraightForward(int steps)
        {
            Console.WriteLine("Did {0} steps forward...", steps);
        }

        public virtual void TurnRight()
        {
            Console.WriteLine("Turned right...");
        }

        public virtual void TurnLeft()
        {
            Console.WriteLine("Turned left...");
        }

        public virtual void DefuseBomb()
        {
            Console.WriteLine("Cut red or green or blue wire...");
        }
    }

 

Main methods that do the stuff are WalkStraightForward, TurnRight, TurnLeft, DefuseBomb. Methods to connect wirelessly and IsConnected are just for imitating reality of this app. You could omit how it works internally.

Here we have Proxy implementation. It always has reference to real object and often implements same interface if is not derived from object’s class.

    public class RobotBombDefuserProxy : RobotBombDefuser
    {
        private RobotBombDefuser _robotBombDefuser;
        private int _communicationWaveLength;
        private int _connectionAttempts = 3;

        public RobotBombDefuserProxy(int communicationWaveLength)
        {
            _robotBombDefuser = new RobotBombDefuser();
            _communicationWaveLength = communicationWaveLength;
        }

        public virtual void WalkStraightForward(int steps)
        {
            EnsureConnectedWithRobot();
            _robotBombDefuser.WalkStraightForward(steps);
        }

        public virtual void TurnRight()
        {
            EnsureConnectedWithRobot();
            _robotBombDefuser.TurnRight();
        }

        public virtual void TurnLeft()
        {
            EnsureConnectedWithRobot();
            _robotBombDefuser.TurnLeft();
        }

        public virtual void DefuseBomb()
        {
            EnsureConnectedWithRobot();
            _robotBombDefuser.DefuseBomb();
        }

        private void EnsureConnectedWithRobot()
        {
            if (_robotBombDefuser == null)
            {
                _robotBombDefuser = new RobotBombDefuser();
                _robotBombDefuser.ConnectWireless(_communicationWaveLength);
            }

            for (int i = 0; i < _connectionAttempts; i++)
            {
                if (_robotBombDefuser.IsConnected() != true)
                {
                    _robotBombDefuser.ConnectWireless(_communicationWaveLength);
                }
                else
                {
                    break;
                }
            }
            if(_robotBombDefuser.IsConnected() != true)
            {
                throw new BadConnectionException("No connection with remote bomb diffuser robot could be made after few attempts.");
            }
        }
    }

So our proxy simply redirects requests to real object and before doing so it always ensures that connection is established, and if it is not it establishes it with three attempts and if it couldn’t it then throws an exception.

So let’s see usage:

        public static void Run()
        {
            int opNum = 0;
            try
            {
                var proxy = new RobotBombDefuserProxy(41);
                proxy.WalkStraightForward(100);
                opNum++;
                proxy.TurnRight();
                opNum++;
                proxy.WalkStraightForward(5);
                opNum++;
                proxy.DefuseBomb();
                opNum++;

                Console.WriteLine();
            }
            catch (BadConnectionException e)
            {
                Console.WriteLine("Exception has been caught with message: ({0}). Decided to have human operate robot there.", e.Message);

                PlanB(opNum);
            }
        }

        private static void PlanB(int nextOperationNum)
        {
            RobotBombDefuser humanOperatingRobotDirectly = new RobotBombDefuser();

            if(nextOperationNum == 0)
            {
                humanOperatingRobotDirectly.WalkStraightForward(100);
                nextOperationNum++;
            }
            if (nextOperationNum == 1)
            {
                humanOperatingRobotDirectly.TurnRight();
                nextOperationNum++;
            }
            if (nextOperationNum == 2)
            {
                humanOperatingRobotDirectly.WalkStraightForward(5);
                nextOperationNum++;
            }
            if (nextOperationNum == 3)
            {
                humanOperatingRobotDirectly.DefuseBomb();
            }
        }
    }

In sample code above you can see usage of the defuser proxy, there is also “plan B”, when direct instance of the defuser is created and used. Code might look bit complex, because of that opNum and nextOperationNum noise. I added it to ensure robot continues it work from where it stopped.

Output:

Did 100 steps forward…

Turned right…

Exception has been caught with message: (No connection with remote bomb diffuser robot could be made after few attempts.). Decided to have human operate robot there.

Did 5 steps forward…

Cut red or green or blue wire…

My implementation of this Design Pattern is slightly different from its original implementation in GoF book where you have two derived classes both from some interface or superclass. But I think in real world implementation with deriving from already existing class is more common. For example such proxy is used always you need to have virtual methods for some framework, say mocking framework or ORM framework.

Here is UML for my example:

image

My Design Patterns Table


No comments


Mediator

February 26, 2011 Design Patterns No comments

Some time have passed since I wrote blog post on GoF Design Pattern. Not sure what are actual reasons for this. I guess passing MS exams, but maybe I was lazy.
I had been thinking about good example for Mediator Design Pattern and could not find anything better than standard example with UI and cooperation of different components, but this was before I thought about neurons and their cooperation and in few moments I realized amazing thing. Our brain is mediator to different body parts. It just amazingly fits description.
Just try to imagine what would happen if each of our body part knows about each other. This means that if you see something great and you want to touch it, your eye has to know about your hands and manipulate them to do this. What if you would need to defense by hands because you got hurt in chest. In this case your chest would need to know about hands and manipulate them. This can be applicable to any part of your body that collects information from world and then some reaction should be done by one or many other body parts. Cooperation many-to-many doesn’t work for our body. But it often happens that developers write code that works just as was described above. Sometimes it works, but sometimes it just creates crappy spaghetti mess. Our body has one central system that does all the analyzing for us and manages reactions. Very often this is good practice for code we write.
MEDIATOR
Mediator is design pattern that centralizes cooperation between components thus decoupling interaction between them.
Mediator gracefully simplifies understanding of interaction between components. This gives better maintainability for future, but because logic is centralized it can become very complex and huge, as human brain is.
Here below is demonstration of the demo application I wrote:
image
So as you can see brain know how to handle different things and how to react on them and with which body parts. How does this happen?
Brain (Mediator) knows about each body part (Colleague), so it actually has properties or fields, like Ear, Eye, Hand, Leg, etc. Each of the body parts knows its brain and can signal that something has happened.

Colleague base class (knows its brain)

        // Colleague
        class BodyPart
        {
            private readonly Brain _brain;

            public BodyPart(Brain brain)
            {
                _brain = brain;
            }

            public void Changed()
            {
                _brain.SomethingHappenedToBodyPart(this);
            }
        }

Concrete implementation of Colleague can look as following:

    class Ear : BodyPart
    {
        private string _sounds = string.Empty;

        public Ear(Brain brain)
            : base(brain)
        {
        }

        public void HearSomething()
        {
            Console.WriteLine("Enter what you hear:");
            _sounds = Console.ReadLine();

            Changed();
        }

        public string GetSounds()
        {
            return _sounds;
        }
    }

So it basically can HearSomething and can provide its status by GetSounds method. Some other body parts can have some reactions, as simple Face implementation below:

    class Face : BodyPart
    {
        public Face(Brain brain)
            : base(brain)
        {
        }

        public void Smile()
        {
            Console.WriteLine("FACE: Smiling...");
        }
    }

Mediator (aka Brain)

As it should be expected Mediator is bit huge class and it has to handle all the complexity of interaction between body parts. You might want to change something in this class, I do not expect you to see this as ideal brain, but I hope you get an idea how it works.
    // Mediator
    class Brain
    {
        public Brain()
        {
            CreateBodyParts();
        }

        private void CreateBodyParts()
        {
            Ear = new Ear(this);
            Eye = new Eye(this);
            Face = new Face(this);
            Hand = new Hand(this);
            Leg = new Leg(this);
        }

        public Ear Ear { get; private set; }
        public Eye Eye { get; private set; }
        public Face Face { get; private set; }
        public Hand Hand { get; private set; }
        public Leg Leg { get; private set; }

        public void SomethingHappenedToBodyPart(BodyPart bodyPart)
        {
            if (bodyPart is Ear)
            {
                string heardSounds = ((Ear)bodyPart).GetSounds();

                if (heardSounds.Contains("stupid"))
                {
                    // attacking offender
                    Leg.StepForward();
                    Hand.HitPersonNearYou();
                    Leg.Kick();
                }
                else if (heardSounds.Contains("cool"))
                {
                    Face.Smile();
                }
            }
            else if (bodyPart is Eye)
            {
                // brain can analyze what you see and
                // can react appropriately using different body parts
            }
            else if (bodyPart is Hand)
            {
                var hand = (Hand)bodyPart;

                bool hurtingFeeling = hand.DoesItHurt();
                if (hurtingFeeling)
                {
                    Leg.StepBack();
                }

                bool itIsNice = hand.IsItNice();
                if (itIsNice)
                {
                    Leg.StepForward();
                    Hand.Embrace();
                }
            }
            else if (bodyPart is Leg)
            {
                // leg can also feel something if you would like it to
            }
        }
    }

Personally I liked example that I’ve prepared. Hope there is no such example over internet, but who knows.

UML

In addition here below is some UML stuff. You can click on image to see it bigger.

image

My design patterns table


No comments


Adapter

January 11, 2011 Design Patterns No comments

For some reason I have thought about good example for Adapter design pattern for a long period of time. There might be straightforward example with two classes, one of which has OperationA and other has OpA and we need to adapt them, but there is no analogy in that example. In this case it would not worse reading this post. Also I thought about example in which we have complex objects with many properties and methods, where you would need to perform some real  conversion. But by the way of thinking there was always electricity adapter in my head circling. In Lviv there is still many apartments where old thin sockets exist, to overcome this people buy small adapters, almost as on the picture on the right, except not that cruel.

So we have our notebook charger that easily fits wide European socket. In your apartment all sockets are new, so you get used to it. Your NewElectricitySystem has method MatchWideSocket. But in your friend’s apartment there is still old one and his OldElectricitySystem has only method MatchThinSocket. Unfortunately you cannot drill sockets in someone else’s flat, you have to buy Adapter, that allows you consume the same electricity, but with old system.

ADAPTER

Adapter – is design pattern that allows us use object, which we cannot change, by providing its functionality thought known interface.

    // Adaptee
    class OldElectricitySystem
    {
        public string MatchThinSocket()
        {
            return "220V";
        }
    }
    // known interface in our code
    interface INewElectricitySystem
    {
        string MatchWideSocket();
    }
    class NewElectricitySystem : INewElectricitySystem
    {
        public string MatchWideSocket()
        {
            return "220V";
        }
    }
    // Adapter
    class Adapter : INewElectricitySystem
    {
        private readonly OldElectricitySystem _adaptee;

        public Adapter(OldElectricitySystem adaptee)
        {
            _adaptee = adaptee;
        }

        // All the magic lives here
        // in our adapter we translate from
        // what we (code) cannot use straightway into what we can
        public string MatchWideSocket()
        {
            return _adaptee.MatchThinSocket();
        }
    }

    class ElectricityConsumer
    {
        // Charging device can be used only with new system
        public static void ChargeNotebook(INewElectricitySystem electricitySystem)
        {
            Console.WriteLine(electricitySystem.MatchWideSocket());
        }
    }

    public class AdapterDemo
    {
        public static void Run()
        {
            // We can easily operate with our new system
            var newElectricitySystem = new NewElectricitySystem();
            ElectricityConsumer.ChargeNotebook(newElectricitySystem);

            // We have to adapt to old system using adapter
            var oldElectricitySystem = new OldElectricitySystem();
            var adapter = new Adapter(oldElectricitySystem);
            ElectricityConsumer.ChargeNotebook(adapter);
        }
    }

Yet another name for this pattern is Wrapper. That is because it wraps functionality of some object, representing it in another interface.

Actually we can also implement it slightly differently than I have it here. In the example above we use composition, but our adapter can easily implement two interfaces of the old and new system and then once created by one of the constructors we would use our adapter in both directions.

My design patterns table


No comments


Facade

January 4, 2011 Design Patterns No comments

Do you like skiing? I do. I even spent two previous days in mountains skiing. Imagine, you decided to spend your weekend very actively in mountains, for this you would need to go and book room in hotel for good night accordingly to your wishes, then you would also need to rent ski, boots and poles. For renting you would be asked questions about your weight and proficiency, then you would be letting them know your height and feetsize for boots, and again height for pole. With all of this on your back you go to ticket office and buy ski pass for one day. Honestly I don’t like this kind of mess. What I would love in this situation is to come to one point, terminal or smth. answer for all questions, pay bill and immediately get your skis, boots, poles, ski pass and room keys. Of course if I have all equipment (I really do) I can take only ticket and go out there.

FACADE

Facade is design pattern that provides us with one entry point to subsystem, simplifying its usage and understanding.

In our example facade would be terminal-serving station (SkiResortFacade), subsystem would be whole bunch of renting buildings, paydesks, hotels. Of course we can go all around the resort, if we like this, but if we take a look from software development point of view if devs will walk all around and use as they wish, it will not lead to positive consequences. And skiers-newcomers will never know where they should go for the first time.

    internal class SkiRent
    {
        public int RentBoots(int feetSize, int skierLevel)
        {
            return 20;
        }
        public int RentSki(int weight, int skierLevel)
        {
            return 40;
        }
        public int RentPole(int height)
        {
            return 5;
        }
    }

    internal class SkiResortTicketSystem
    {
        public int BuyOneDayTicket()
        {
            return 120;
        }
        public int BuyHalfDayTicket()
        {
            return 60;
        }
    }

    internal class HotelBookingSystem
    {
        public int BookRoom(int roomQuality)
        {
            switch (roomQuality)
            {
                case 3:
                    return 250;
                case 4:
                    return 500;
                case 5:
                    return 900;
                default:
                    throw new ArgumentException("roomQuality should be in range [3;5]","roomQuality");
            }
        }
    }

    public class SkiResortFacade
    {
        private SkiRent _skiRent = new SkiRent();
        private SkiResortTicketSystem _skiResortTicketSystem = new SkiResortTicketSystem();
        private HotelBookingSystem _hotelBookingSystem = new HotelBookingSystem();

        public int HaveGoodOneDayRest(int height, int weight, int feetSize, int skierLevel, int roomQuality)
        {
            int skiPrice = _skiRent.RentSki(weight, skierLevel);
            int skiBootsPrice = _skiRent.RentBoots(feetSize, skierLevel);
            int polePrice = _skiRent.RentPole(height);
            int oneDayTicketPrice = _skiResortTicketSystem.BuyOneDayTicket();
            int hotelPrice = _hotelBookingSystem.BookRoom(roomQuality);

            return skiPrice + skiBootsPrice + polePrice + oneDayTicketPrice + hotelPrice;
        }

        public int HaveRestWithOwnSkis()
        {
            int oneDayTicketPrice = _skiResortTicketSystem.BuyOneDayTicket();
            return oneDayTicketPrice;
        }
    }

    public class FacadeDemo
    {
        public static void Run()
        {
            var skiResortFacade = new SkiResortFacade();

            int weekendRestPrice = skiResortFacade.HaveGoodOneDayRest(175, 60, 42, 2, 3);

            Console.WriteLine("Price: {0}", weekendRestPrice);
        }
    }

This design pattern in some way represents very important encapsulation principle but just on higher level. On this level we encapsulate whole subsystem instead of class. Big systems usually consist with many subsystems that communicate between each other by using facades. Space station connects to another station using one mechanism, not with gluing together hundreds of wires and tubes. Also an good way to develop software would be to have some kind of facade (it might be set of known interfaces) inside of each assembly, so it can be used easily from other parts of your application.
Thank you.
My design patterns table


No comments