Design Patterns

Abstract Factory

December 27, 2010 Design Patterns 2 comments

Ok, let’s imagine that you came into toys shop (playing role of Santa) and you want to buy dozen of toys for kids (not necessary for your kids). One kid likes teddy toys, she often goes to bed with them. Other kid prefers solid toys, like wooden or metal. This kid often breaks toys, so you also would prefer to buy something durable. Both of them definitely want a bear and cat toys, they also might want other toy-animals. Fortunately shop is huge and you bought everything. You put wooden toys into one sack and teddy toys into another sack.

Thus when you came to the girl, who likes soft toys, you started getting teddy bear, then teddy cat and other teddy animals requested by kid. When you came to boy you did the same but with another sack, fetching wooden bear and wooden cat out.

ABSTRACT FACTORY

Abstract Factory is design pattern that provides you with interface for creating families of objects without specifying their concrete types. (oh… almost repeated word-by-word GoF guys)

In our example family is toys of some specific type, family consists with Bear and Cat. Abstract Factory is sack. One of the factories returns wooden toys and other teddy toys. Thus when kid asks for cat he/she gets cat appropriately to selected sack.

I hope that analogy example is good. Let’s take a look at some code?

Abstract factory and concrete implementations

Abstract Factory defines interface that returns instances of Bear or Cat (through base class). Concrete factories return concrete implementations of members of the family.

     // abstract factory

public interface IToyFactory
{
Bear GetBear();
Cat GetCat();
}
// concrete factory

public class TeddyToysFactory : IToyFactory
{
public Bear GetBear()
{
return new TeddyBear();
}
public Cat GetCat()
{
return new TeddyCat();
}
}
// concrete factory

public class WoodenToysFactory : IToyFactory
{
public Bear GetBear()
{
return new WoodenBear();
}
public Cat GetCat()
{
return new WoodenCat();
}
}

This is quite obvious, that once we have instance of factory we are ready to produce members of the families. Let’s take a look on usage:

            // lets start with wooden factory

IToyFactory toyFactory = new WoodenToysFactory();

Bear bear = toyFactory.GetBear();
Cat cat = toyFactory.GetCat();
Console.WriteLine("I've got {0} and {1}", bear.Name, cat.Name);
// Output: [I've got Wooden Bear and Wooden Cat]

/*--------------
somewhere else in the code...

----------------*/

// and now teddy one
IToyFactory toyFactory = new TeddyToysFactory();

Bear bear = toyFactory.GetBear();
Cat cat = toyFactory.GetCat();
Console.WriteLine("I've got {0} and {1}", bear.Name, cat.Name);
// Output: [I've got Teddy Bear and Teddy Cat]

Two snippets of code are almost identical, except of concrete sack.

If you are still interested in realization of animals-toys just take a quick look on this:

    public abstract class AnimalToy
{
protected AnimalToy(string name)
{
Name = name;
}
public string Name { get; private set; }
}
public abstract class Cat : AnimalToy
{
protected Cat(string name) : base(name) { }
}
public abstract class Bear : AnimalToy
{
protected Bear(string name) : base(name) { }
}
class WoodenCat : Cat
{
public WoodenCat() : base("Wooden Cat") { }
}
class TeddyCat : Cat
{
public TeddyCat() : base("Teddy Cat") { }
}
class WoodenBear : Bear
{
public WoodenBear() : base("Wooden Bear") { }
}
class TeddyBear : Bear
{
public TeddyBear() : base("Teddy Bear") { }
}

Abstract factory is very widely used design pattern. Extremely good example would be ADO.NET  DbProviderFactory class, i.e. abstract factory, which defines interface for getting DbCommand, DbConnection, DbParameter  and so on. Concrete factory SqlClientFactory returns appropriately SqlCommand, SqlConnection…

Thank you for reading this post till the end.

 My design patterns table


2 comments


Strategy

December 14, 2010 Design Patterns 2 comments

“That’s simple as door” I wrote in Ukrainian, but I’m quite sure that in English another word combination is used to refer to express simple things. When it is raining outside you wear coat and take umbrella, and when it is sweltering you take T-shirt and sunglasses. But instead of taking a look outside to identify the weather and walk to wardrobe and take clothes and then, keeping in mind weather condition walk to bracket and take sunglasses or umbrella, YOU wake up and your wife (or husband, what is less likely) gives everything you need. In other words your wearing strategy for today has been given to you with one shot.

STRATEGY

Strategy – is design pattern that means having family of algorithms that can be used/changed by your code depending on situation.
Lets imagine that in class Myself we have some method GoOutside()  where we chose clothes and accessories and then walking outside.
Method could possibly look like below:
        public void GoOutside()
        {
            var weather = Weather.GetWeather();
            string clothes = GetClothes(weather);
            string accessories = GetAccessories(weather);
            Console.WriteLine("Today I wore {0} and took {1}", clothes, accessories);
        }

        private string GetAccessories(string weather)
        {
            string accessories;
            switch (weather)
            {
                case "sun":
                    accessories = "sunglasses";
                    break;
                case "rain":
                    accessories = "umbrella";
                    break;
                default:
                    accessories = "nothing";
                    break;
            }
            return accessories;
        }

        private string GetClothes(string weather)
        {
            string clothes;
            switch (weather)
            {
                case "sun":
                    clothes = "T-Shirt";
                    break;
                case "rain":
                    clothes = "Coat";
                    break;
                default:
                    clothes = "Shirt";
                    break;
            }
            return clothes;
        }
It doesn’t offend anyone, but once we will need to adapt to snow shower, we would need add one more case in 300 more places. From one point of view that is not difficult, but from another it “can get you” or maybe code with method GoOuside cannot be changed any longer. What’s then?
Hereabove I showed example with switch statement, since Strategy is the most elegant way to get rid of this monster.
    internal class Myself
    {
        private IWearingStrategy _wearingStrategy = new DefaultWearingStrategy();

        public void ChangeStrategy(IWearingStrategy wearingStrategy)
        {
            _wearingStrategy = wearingStrategy;
        }

        public void GoOutside()
        {
            var clothes = _wearingStrategy.GetClothes();
            var accessories = _wearingStrategy.GetAccessories();

            Console.WriteLine("Today I wore {0} and took {1}", clothes, accessories);
        }
    }
As we can see interface has two methods. They are shown below as well as SunshineWearingStrategy implementation:
    public interface IWearingStrategy
    {
        string GetClothes();
        string GetAccessories();
    }

    class SunshineWearingStrategy : IWearingStrategy
    {
        public string GetClothes()
        {
            return "T-Shirt";
        }

        public string GetAccessories()
        {
            return "sunglasses";
        }
    }

All left is to correctly chose strategy and set it for Myself instance. Hm! Anyway someone have to take a look on weather and put right strategy (wife, who woke up in the morning). But we can do this in one different place.

            var me = new Myself();
            me.ChangeStrategy(new RainWearingStrategy());
            me.GoOutside();

Output: “Today I wore Coat and took umbrella”

Yet another example would be changing sorting algorithm depending on list length. We all know that qsort is not best solution for small collections or superlarge, in one case we would use merge or other sorting and in another case we would use heapsort. Having sorting logic separately and changing it depending on the size of collection is good example of Stategy design pattern.

My design patterns table


2 comments


Chain Of Responsibility

December 7, 2010 Design Patterns 2 comments

Imagine that you went to cafe with your friends. Cafe is somewhat weird, there is not enough room, and you have to pass food to other person if it is not for you. Your best friend took place the most closed to end of the table, so he is first who gets order. Cause he slept not enough in the night he dies for at least one cap of something with coffee and a lot of meat, since he did not eat during the day. Next to your friend is you and then your girlfriend near the wall. You want soup and she wants cappuccino. She have none to pass food to.

Chain Of Responsibility

I hope that whole mechanics of the design pattern Chain Of Responsibility is understandable. We have some set or chin of handlers (visitors of cafe), that can handle command (food in our example). If handler cannot process command it passes it to its successor if it exists.

Handler

In our example general interface for handler could be following abstract base class:

    public abstract class WierdCafeVisitor
{
public WierdCafeVisitor CafeVisitor { get; private set; }

protected WierdCafeVisitor(WierdCafeVisitor cafeVisitor)
{
CafeVisitor = cafeVisitor;
}

public virtual void HandleFood(Food food)
{
// If I cannot handle other food, passing it to my successor
if (CafeVisitor != null)
{
CafeVisitor.HandleFood(food);
}
}
}

As we can see by default food is passed to next cafe visitor in chain, if it exists.

Lets now take a look on realization that is more suitable for your persnickety friend:

    public class BestFriend : WierdCafeVisitor
{
public List<Food> CoffeeContainingFood { get; private set; }
public BestFriend(WierdCafeVisitor cafeVisitor) : base(cafeVisitor)
{
CoffeeContainingFood = new List<Food>();
}

public override void HandleFood(Food food)
{
if(food.Ingradients.Contains("Meat"))
{
Console.WriteLine("BestFriend: I just ate {0}. It was testy.", food.Name);
return;
}
if (food.Ingradients.Contains("Coffee") && CoffeeContainingFood.Count < 1)
{
CoffeeContainingFood.Add(food);
Console.WriteLine("BestFriend: I have to take something with coffee. {0} looks fine.", food.Name);
return;
}
base.HandleFood(food);
}
}

Implementations of two other handlers – Me and GirlFriend probably are understandable, but anyway will show realization of GirlFriend visitor:

    public class GirlFriend : WierdCafeVisitor
{
public GirlFriend(WierdCafeVisitor cafeVisitor) : base(cafeVisitor)
{
}

public override void HandleFood(Food food)
{
if(food.Name == "Cappuccino")
{
Console.WriteLine("GirlFriend: My lovely cappuccino!!!");
return;
}
base.HandleFood(food);
}
}

That’s simple: girl wants cappuccino, but since she is last in chain she will not get it before friend will not have his cap of something with coffee.

Usage

Now lets take a look on usage. We create two cappuccinos, two soups and one meat. Then we pass those one by one into BestFriend hands: 

            var cappuccino1 = new Food("Cappuccino", new List<string> {"Coffee", "Milk", "Sugar"});
var cappuccino2 = new Food("Cappuccino", new List<string> {"Coffee", "Milk"});

var soup1 = new Food("Soup with meat", new List<string> {"Meat", "Water", "Potato"});
var soup2 = new Food("Soup with potato", new List<string> {"Water", "Potato"});
var meat = new Food("Meat", new List<string> {"Meat"});

var girlFriend = new GirlFriend(null);
var me = new Me(girlFriend);
var bestFriend = new BestFriend(me);

bestFriend.HandleFood(cappuccino1);
bestFriend.HandleFood(cappuccino2);
bestFriend.HandleFood(soup1);
bestFriend.HandleFood(soup2);
bestFriend.HandleFood(meat);

Output:

BestFriend: I have to take something with coffee. Cappuccino looks fine.
GirlFriend: My lovely cappuccino!!!
BestFriend: I just ate Soup with meat. It was testy.
Me: I like Soup. It went well.
BestFriend: I just ate Meat. It was testy.

As we can see from output girl got only second cappuccino and you have been forced to eat soup without meat :)

What is also interesting is that we can add another one handler after girlfriend, say bag for dog, and everything that none likes will go there.

My design patterns table


2 comments


Observer

November 30, 2010 Design Patterns No comments

Many people like watching box fights. But besides of this, someone have to pay for all of this, and most of the money come from people who put some money on boxers and then lose it. Or… maybe I’m wrong, but for this example, let it be so. Imagine that we have box fight tonight and there are two persons interested in game, so they OBSERVE fight and UPDATE their rates. One of them likes risks, so he always put money on boxer who has less chance to win, and other is very conservative and likes small bird in hand instead of big in the sky.

OBSERVER

Observer is design pattern, that allows automatically update many observers if there was change in state of some subject object.

So, each gambler (Player, Observer) likes to adjust his rates, that is why he has Update() method.

    public interface IObserver
{
void Update(ISubject subject);
}

public class RiskyPlayer : IObserver
{
public string BoxerToPutMoneyOn { get; set; }

public void Update(ISubject subject)
{
var boxFight = (BoxFight)subject;

BoxerToPutMoneyOn = (boxFight.BoxerAScore > boxFight.BoxerBScore) ? "I put on boxer B, if he win I get more!" : "I put on boxer A, if he win I get more!";


Console.WriteLine("RISKYPLAYER:{0}", BoxerToPutMoneyOn);
}
}

public class ConservativePlayer : IObserver
{
public string BoxerToPutMoneyOn { get; set; }

public void Update(ISubject subject)
{
var boxFight = (BoxFight)subject;

BoxerToPutMoneyOn = (boxFight.BoxerAScore < boxFight.BoxerBScore) ? "I put on boxer B, better be safe!" : "I put on boxer A, better be safe!";

Console.WriteLine("CONSERVATIVEPLAYER:{0}", BoxerToPutMoneyOn);
}
}

Here below we have subject which is observed by players:

    public interface ISubject
{
void AttachObserver(IObserver observer);
void DetachObserver(IObserver observer);
void Notify();
}

public class BoxFight : ISubject
{
public List<IObserver> Observers { get; private set; }
public int RoundNumber { get; private set; }

private Random Random = new Random();

public int BoxerAScore { get; set; }
public int BoxerBScore { get; set; }

public BoxFight()
{
Observers = new List<IObserver>();
}

public void AttachObserver(IObserver observer)
{
Observers.Add(observer);
}

public void DetachObserver(IObserver observer)
{
Observers.Remove(observer);
}

public void NextRound()
{
RoundNumber++;

BoxerAScore += Random.Next(0, 5);
BoxerBScore += Random.Next(0, 5);

Notify();
}

public void Notify()
{
foreach (var observer in Observers)
{
observer.Update(this);
}
}
}

Usage, or how we build one-to-many relationship by attaching observer-s:

            var boxFight = new BoxFight();

var riskyPlayer = new RiskyPlayer();
var conservativePlayer = new ConservativePlayer();

boxFight.AttachObserver(riskyPlayer);
boxFight.AttachObserver(conservativePlayer);


boxFight.NextRound();
boxFight.NextRound();
boxFight.NextRound();
boxFight.NextRound();

Output:

RISKYPLAYER:I put on boxer A, if he win I get more!
CONSERVATIVEPLAYER:I put on boxer B, better be safe!

RISKYPLAYER:I put on boxer B, if he win I get more!
CONSERVATIVEPLAYER:I put on boxer A, better be safe!

RISKYPLAYER:I put on boxer B, if he win I get more!
CONSERVATIVEPLAYER:I put on boxer A, better be safe!

RISKYPLAYER:I put on boxer B, if he win I get more!
CONSERVATIVEPLAYER:I put on boxer A, better be safe!

 

Been very short explanation. Just take closer look on interfaces in examples, this should be enough to understand everything.

My design patterns table


No comments


Composite

November 23, 2010 Design Patterns No comments

Did you ever think why so many things around us have tree-similar structure? Top management of your company can delegate some work to middle management, and it can delegate it to your direct manager, who will ask you  and your colleagues do something. In one of your tasks you had to gather data for some customer into xml. XML has also tree-similar structure. Why? Because it is the best way to serialize data, that can have data, that can… You got that! Now imagine that you want to gather data for some document part by part.

 

COMPOSITE

Composite is design pattern that provides us tree-similar structural representing of classes, this allows us work uniformly with parents and Childs.
So interface that defines common requirements for parents and kids:

    public interface IDocumentComponent
    {
        string GatherData();
        void AddComponent(IDocumentComponent documentComponent);
    }

And here we see some leaf component implementation. It is Customer Component, which gathers some data about customer basing on id provided to the class.

    public class CustomerDocumentComponent : IDocumentComponent
    {
        private int CustomerIdToGatherData { get; set; }

        public CustomerDocumentComponent(int customerIdToGatherData)
        {
            CustomerIdToGatherData = customerIdToGatherData;
        }

        public string GatherData()
        {
            string customerData;
            switch (CustomerIdToGatherData)
            {
                case 41:
                    customerData = "Andriy Buday";
                    break;
                default:
                    customerData = "Someone else";
                    break;
            }

            return string.Format("<Customer>{0}</Customer>", customerData);
        }

        public void AddComponent(IDocumentComponent documentComponent)
        {
            Console.WriteLine("Cannot add to leaf...");
        }
    }

And not-leaf implementation of the component below. Please take into account that it simply loops through Childs and executes GatherData method.

    public class DocumentComponent : IDocumentComponent
    {
        public string Name { get; private set; }
        public List<IDocumentComponent> DocumentComponents { get; private set; }

        public DocumentComponent(string name)
        {
            Name = name;
            DocumentComponents = new List<IDocumentComponent>();
        }

        public string GatherData()
        {
            var stringBuilder = new StringBuilder();
            stringBuilder.AppendLine(string.Format("<{0}>", Name));
            foreach (var documentComponent in DocumentComponents)
            {
                documentComponent.GatherData();
                stringBuilder.AppendLine(documentComponent.GatherData());
            }
            stringBuilder.AppendLine(string.Format("</{0}>", Name));

            return stringBuilder.ToString();
        }

        public void AddComponent(IDocumentComponent documentComponent)
        {
            DocumentComponents.Add(documentComponent);
        }
    }

Gluing parts to be some kind of document:

            var document = new DocumentComponent("ComposableDocument");
            var headerDocumentSection = new HeaderDocumentComponent();
            var body = new DocumentComponent("Body");
            document.AddComponent(headerDocumentSection);
            document.AddComponent(body);

            var customerDocumentSection = new CustomerDocumentComponent(41);
            var orders = new DocumentComponent("Orders");
            var order0 = new OrderDocumentComponent(0);
            var order1 = new OrderDocumentComponent(1);
            orders.AddComponent(order0);
            orders.AddComponent(order1);

            body.AddComponent(customerDocumentSection);
            body.AddComponent(orders);

            string gatheredData = document.GatherData();

            Console.WriteLine(gatheredData);

Output is somewhat similar to XML. At least I tried to keep it similar.

<ComposableDocument>

<Header><MessageTime>8:47:23</MessageTime></Header>

<Body>

  <Customer>Andriy Buday</Customer>

  <Orders>

   <Order>Kindle;Book1;Book2</Order>

   <Order>Phone;Cable;Headset</Order>

  </Orders>

</Body>

</ComposableDocument>

Also GoF guys suggest having Remove(Component) and GetChild(int) methods in your Component, so you might want to add them. Just don’t limit yourself with any kind of explanations. You might have some unique need.

My design patterns table


No comments


Command

November 15, 2010 Design Patterns 4 comments

You have a boss, who doesn’t care who will be doing some work or how it will be done, he just want it to be started and completed at some point of time, say after customer signed contract. Since you are at high position you were asked to form team A that will be working at some project X, you also got list of high-level requirements from your boss. You should be ready to start all work at the moment your customer signs contract.

COMMAND

So you are Command – you encapsulate receiver team A and parameters to start work (project and requirements). Team and requirements are given to you by your boss – Client.

You are able to delegate all work to team A and provide requirements at the moment customer triggers process. Your customer is Invoker, they have contact to you, so can use you as they want.

Command – is design pattern that allows us encapsulate request, tune it with parameters as needed and then execute at one point of time, without knowing how actually executes work.

Client code

Here is how story looks from code perspective. Taking a look at client code (boss):

            var customer = new Customer();

// for some reason boss always knows that company has money
// only for team Z
var team = new Team("Z");
// he also managed to get high-level list of requirements for you
var requirements = new List<Requirement>() { new Requirement("Cool web site"), new Requirement("Ability to book beer on site") };
// you should be ready to be invoked by Customer
ICommand commandX = new YouAsProjectManagerCommand(team, requirements);

customer.AddCommand(commandX);

// there is also here developer who can code at light speed
var heroDeveloper = new HeroDeveloper();
// boss decided to give him project A
ICommand commandA = new HeroDeveloperCommand(heroDeveloper, "A");

customer.AddCommand(commandA);

// when customer signs contract with boss
// your team and hero developer start executing their job
customer.SignContractWithBoss();

Command

Now lets take a look on two concrete commands:

    public interface ICommand
{
void Execute();
}


public class YouAsProjectManagerCommand : ICommand
{
public YouAsProjectManagerCommand(Team team, List<Requirement> requirements)
{
Team = team;
Requirements = requirements;
}

public void Execute()
{
// implementation delegates work to concrete receiver
Team.CompleteProject(Requirements);
}

protected Team Team { get; set; }
protected List<Requirement> Requirements { get; set; }
}

public class HeroDeveloperCommand : ICommand
{
public HeroDeveloperCommand(HeroDeveloper heroDeveloper, string projectName)
{
HeroDeveloper = heroDeveloper;
ProjectName = projectName;
}

protected HeroDeveloper HeroDeveloper { get; set; }
public string ProjectName { get; set; }

public void Execute()
{
// implementation delegates work to concrete receiver
HeroDeveloper.DoAllHardWork(ProjectName);
}
}

Receiver

Team and HeroDeveloper are receivers of work that should be done.

Invoker

Customer simply aggregates many commands and without knowing how those commands were built by boss. Customer as true invoker simply triggers work using Execute method:

    public class Customer
{
public Customer()
{
Commands = new List<ICommand>();
}

public void AddCommand(ICommand command)
{
Commands.Add(command);
}

protected List<ICommand> Commands { get; set; }

public void SignContractWithBoss()
{
foreach (var command in Commands)
{
command.Execute();
}
}
}

Output

User Story (Cool web site) has been completed

User Story (Ability to book beer on site) has been completed

Hero developer completed project (A) without requirements in manner of couple of hours!

UPDATE: Nov 18, 2010

UML-Diagram

Here below I added diagram showing two commands exactly as in example. Please take into account that for simplicity you can remove one pair HeroDeveloperCommand-HereDeveloper. Also take into consideration that in our example concrete commands are aggregating receivers, but this is not common situation. In most cases receiver is some another system.

image


4 comments


Bridge

November 8, 2010 Design Patterns 2 comments

Imagine that you own huge building company. It builds houses and apartment blocks all around your city. Building are of two types – either built with concrete blocks or with bricks. Since you are boss when you were deciding how to divide work you have decided that all crews will have same operations like BuildFoundation, BuildRoom, BuildRoof. But because houses are of two types you had to always keep two teams (aka. two concrete).
Once it turned out that couple of buildings were of mixed type where you had to build some rooms with concrete blocks and some with bricks. For this reason you had to move whole teams from one part of the city to another. You got many complains from your employees, they suggested moving only that part of team that is specialized in building rooms, so you can easily move small crew of workers and reassign it easily to any team instead of having two separate teams. And that is idea.

BRIDGE

Bridge is design pattern that allows you decouple realization from its abstraction, therefore your realization can be changed separately from abstraction because does not implement it directly.
In other words, our IBuildingCompany might have two concrete realizations like NearSeeBuildingCompany and CityBuildingCompany, each of them does probably something different for their foundation and roof, but at the same time we can easily and quickly reassign WallCreator crew for each of those companies to build either brick or either concrete walls.

Let say we have BuildingCompany as below:

    internal interface IBuldingCompany
    {
        void BuildFoundation();
        void BuildRoom();
        void BuildRoof();

        IWallCreator WallCreator { get; set; }
    }

    internal class BuldingCompany : IBuldingCompany
    {
        public void BuildFoundation()
        {
            Console.WriteLine("Foundation is built.{0}", Environment.NewLine);
        }

        public void BuildRoom()
        {
            WallCreator.BuildWallWithDoor();
            WallCreator.BuildWall();
            WallCreator.BuildWallWithWindow();
            WallCreator.BuildWall();

            Console.WriteLine("Room finished.{0}", Environment.NewLine);
        }

        public IWallCreator WallCreator { get; set; }

        public void BuildRoof()
        {
            Console.WriteLine("Roof is done.{0}", Environment.NewLine);
        }
    }

So what is so interested about it? Answer is property WallCreator, which is exactly our bridge to implementation.

Usage code

Let see this in action:

            // We have two wall creating crews - concrete blocks one and bricks one
            var brickWallCreator = new BrickWallCreator();
            var conctreteSlabWallCreator = new ConcreteSlabWallCreator();

            var buildingCompany = new BuldingCompany();
            buildingCompany.BuildFoundation();

            buildingCompany.WallCreator = conctreteSlabWallCreator;
            buildingCompany.BuildRoom();

            // Company can easily switch to another wall crew to continue building rooms
            // with another material
            buildingCompany.WallCreator = brickWallCreator;
            buildingCompany.BuildRoom();
            buildingCompany.BuildRoom();

            buildingCompany.BuildRoof();

Isn’t it awesome? Output should be intuitive, but since I did not show implementations of BrickWallCreator and ConcreteSlabWallCreator I’m going to list it below:

Foundation is built.
Concrete slab wall with door.

Concrete slab wall.

Concrete slab wall with window.

Concrete slab wall.

Room finished.
Brick wall with door.

Brick wall.

Brick wall with window.

Brick wall.

Room finished.
Brick wall with door.

Brick wall.

Brick wall with window.

Brick wall.

Room finished.
Roof is done.

UML diagram illustrates how this pattern looks like and why it is called bridge.

image
My design patterns table


2 comments