9 листопада 2010 р.

"Патерн Вівторка" #14: Міст (Bridge)

Уявімо, що ви володієте будівельною компанією, яка будує дачні будинки і житлові масиви. Зазвичай будівлі є двох типів - або із цегли або із бетонних плит. Оскільки ви бос, то ви вирішили поділити всіх ваших робітників на команди, які будуть вміти робити одні і ті ж операції: BuildFoundation, BuildRoom, BuildRoof. Але оскільки будівлі двох типів вам завжди приходиться тримати два типи різних команд (конкретних команд).

Одного разу виявилося що будівлі можуть бути побудовані із бетонних і цегляних стін одночасно. Так як у кожній із команд вміли працювати тільки із одним типом стін ви були змушені переміщати цілі команди із одного закутка міста в інший. Працівники почали жалітися і навіть запропонували вирішення проблеми. Пропозиція полягає у виділенні маленьких бригад, які спеціалізуються в будуванні кімнат або із бетонних або із цегляних стін. Таким чином тільки ці бригади і можна буде перевозити із одного закутка міста в інше, замість того, щоб мати окремі великі команди. От вона ідея!

МІСТ



Міст - це такий дизайн патерн, що дозволяє розділити імплементацію від її абстракції, таким чином реалізація може бути змінена окремо від абстракції, оскільки вона не наслідується від неї напряму.

Іншими словами наш інтерфейс IBuildingCompany може мати дві конкретні реалізації, такі як NearSeeBuildingCompany та CityBuildingCompany, кожна із яких напевно якось по своєму робить фундамент та кришу, оскільки грунт інший і погода також, але в той же час ми можемо просто і легко змінити реалізацію бригади побудови стін - WallCreator для будь-якої із компаній, щоб будувати або цегляні або бетонні стіни.


Нумо глянемо на BuildingCompany:

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);
        }
    }

І що тут цікавого? Відповідь - властивість WallCreator, яка якраз і є мостом до реалізації.



Код використання


Глянемо на "міст" в дії:

// Ми маємо дві бригади - одна працює із цеглою а інша із бетоном
var brickWallCreator = new BrickWallCreator();
            var conctreteSlabWallCreator = new ConcreteSlabWallCreator();

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

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

            // Компанія може легко переключитися на іншу команду, яка буде будувати
// стіни із інших матеріалів
buildingCompany.WallCreator = brickWallCreator;
            buildingCompany.BuildRoom();
            buildingCompany.BuildRoom();

            buildingCompany.BuildRoof();

Хіба це не чудово? Вивід, я припускаю, є інтуїтивним, але оскільки я не наводив реалізацій класів BrickWallCreator та ConcreteSlabWallCreator подивимося на нього:

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 - діаграма нижче зображає як структура цього дизайн патерну виглядає і чому його взагалі назвали мостом.



image

Моя табличка патернів
Developer's RoadMap To Success

Немає коментарів:

Дописати коментар