Сказки о Design Patterns. Factory Method.

Aug 26, 2012 14:46

После того, как озаботился толстый хорёк сорос созданием директоров с билдерами, стал он думать, как бы ему всю эту бодягу автоматизировать. Думал, думал и придумал. Ведь абстрактные фабрики у него уже есть, просто фабрики тоже - осталось им только фабричный метод добавить, чтобы всё это вместе связать и всё! Фабричный метод он ведь что делает? Ему параметр передали(каталоговый номер детали к примеру), он идёт и решает какого ему билдера вызвать, чтобы нужную деталь вернуть. А чего уж там дальше с ней делать будут... В общем сиди, отдыхай, виски пьянствуй, только на самом верхнем уровне команды отдавай, а дальше оно само все сделается. Лепота!



Builder module:
using System;

namespace DesignPatterns
{
    public enum DetailMaterial
    {
        Plastic,
        StainlessSteel,
        Wood,
        Leather,
    }
    // Builder - абстрактный интерфейс для создания деталей
    abstract class DetailBuilder
    {
        protected Detail detail;

public Detail GetDetail()
        {
            return detail;
        }

public void CreateNewDetail()
        {
            detail = new Detail();
        }

public abstract void BuildByDetailPlan();
        public abstract void SetMaterial();
    }
    // Concrete Builder - имплементация билдера, умеет создавать крылья по заранее известным размерам.
    // Разумеется, имплементация не настоящая, приводится только как пример.
    // Интересно, что это обьект, который умеет создавать другие обьекты.
    class WingBuilder : DetailBuilder
    {
        public override void BuildByDetailPlan()
        {
            detail.DetailPlan = new Point[] { new Point(0, 0), new Point(10, 10), new Point(1877, 1890) };
        }

public override void SetMaterial()
        {
            detail.Material = DetailMaterial.StainlessSteel;
        }
    }
    // Concrete Builder - имплементация билдера, умеет создавать танковые пушки по заранее известным размерам.
    class GanBuilder : DetailBuilder
    {
        public override void BuildByDetailPlan()
        {
            detail.DetailPlan = new Point[] { new Point(0, 0), new Point(40, 10), new Point(287, 1830) };
        }

public override void SetMaterial()
        {
            detail.Material = DetailMaterial.StainlessSteel;
        }
    }

// Concrete Builder - имплементация билдера, умеет создавать сопло для космического корабля по заранее известным размерам.
    class JetBuilder : DetailBuilder
    {
        public override void BuildByDetailPlan()
        {
            detail.DetailPlan = new Point[] { new Point(0, 0), new Point(10, 50), new Point(2817, 2830) };
        }

public override void SetMaterial()
        {
            detail.Material = DetailMaterial.StainlessSteel;
        }
    }

// Director - отвечает за правильное создание деталей.
    // Получает Concrete Builder в качестве параметра и запускает на нем все необходимые операции.
    class Director
    {
        private DetailBuilder _detailBuilder;

public void SetDetailBuilder(DetailBuilder pb)
        {
            _detailBuilder = pb;
        }

public Detail GetDetail()
        {
            return _detailBuilder.GetDetail();
        }

public void ConstructDetail()
        {
            _detailBuilder.CreateNewDetail();
            _detailBuilder.BuildByDetailPlan();
            _detailBuilder.SetMaterial();
        }
    }

// Деталь - Будет создана директором с использованием билдера
    public class Detail
    {
        public Point[] DetailPlan; //Чертеж детали по точкам
        public DetailMaterial Material; //Из чего деталь делать
    }
    // Точка на чертеже проекции детали
    public class Point
    {
        private double _x;  //х координата точки

public double X
        {
            get { return _x; }
            set { _x = value; }
        }
        private double _y;  //у координата точки

public double Y
        {
            get { return _y; }
            set { _y = value; }
        }

public Point(double x, double y)
        {
            _x = x;
            _y = y;
        }

}

// Для тестов на консоли
    //class Program
    //{
    //    static void Main(string[] args)
    //    {
    //        DetailBuilder wingBuilder = new WingBuilder();
    //        Director director = new Director();
    //        director.SetDetailBuilder(wingBuilder);
    //        director.ConstructDetail();
    //        // создание детали
    //        Detail wing = director.GetDetail();

//        DetailBuilder ganBuilder = new GanBuilder();
    //        director.SetDetailBuilder(ganBuilder);
    //        director.ConstructDetail();
    //        // создание детали
    //        Detail gan = director.GetDetail();
    //    }
    //}

}

Code:
using System;
using System.Configuration;
using System.Collections.Generic;

namespace DesignPatterns
{
#region Интерфейсы

public interface IMilitaryEquipment
{
void Shoot();
void AddConstructionDetail(Detail detail);
}

public interface IMilitaryEquipmentFactory
{
IMilitaryEquipment CreateEquipment();
}

#endregion

#region Fabric Method

public static class FabricMethod
{
//Второй пример фабричного метода
public static void ConstructEquipment(IMilitaryEquipment equipment)
{
Director director = new Director();
director.SetDetailBuilder(SetEquipmentBuilder(equipment));
director.ConstructDetail();
// создаем деталь
Detail detail = director.GetDetail();
// прикручиваем деталь к машине
equipment.AddConstructionDetail(detail);
//Потом прикручиваем остальные детали и готовая машина уходит к заказчику
}

private static DetailBuilder SetEquipmentBuilder(IMilitaryEquipment equipment)
{
DetailBuilder equipmentBuilder;
if (equipment is Panzer)
{
equipmentBuilder = new GanBuilder();
}
else if (equipment is Aircraft)
{
equipmentBuilder = new WingBuilder();
}
else if (equipment is Spaceship)
{
equipmentBuilder = new JetBuilder();
}
else
{
//Пушки нужны всем ;)
equipmentBuilder = new GanBuilder();
}
return equipmentBuilder;
}
}

#endregion

#region Конкретные фабрики

public class PanzerFactory : IMilitaryEquipmentFactory
{
IMilitaryEquipment IMilitaryEquipmentFactory.CreateEquipment()
{
Panzer panzer=new Panzer();
FabricMethod.ConstructEquipment(panzer);
return panzer;
}
}

public class AircraftFactory : IMilitaryEquipmentFactory
{
IMilitaryEquipment IMilitaryEquipmentFactory.CreateEquipment()
{
Aircraft aircraft=new Aircraft();
FabricMethod.ConstructEquipment(aircraft);
return aircraft;
}
}

public class SpaceshipFactory : IMilitaryEquipmentFactory
{
IMilitaryEquipment IMilitaryEquipmentFactory.CreateEquipment()
{
Spaceship spaceship=new Spaceship();
FabricMethod.ConstructEquipment(spaceship);
return spaceship;
}
}

#endregion

#region Обьекты военной техники

//Базовый обьект военной техники. Нужен для того, чтобы хранить поля класса.
public class MilitaryEquipment:IMilitaryEquipment
{
private List _equipmentDetails=new List();

public List EquipmentDetails
{
get { return _equipmentDetails; }
set { _equipmentDetails = value; }
}

public void AddEquipmentDetail(Detail detail,string equipmentName)
{
_equipmentDetails.Add(detail);
System.Console.WriteLine("Detail {0} added to {1}",detail.ToString(),equipmentName);
}
}
//танк
public class Panzer : MilitaryEquipment
{
public void Shoot()
{
System.Console.WriteLine("Tank fires!");
}

public void AddConstructionDetail(Detail detail)
{
base.AddEquipmentDetail(detail,"panzer");
}

}
//самолет
public class Aircraft : MilitaryEquipment
{
public void Shoot()
{
System.Console.WriteLine("Aircraft fires!");
}

public void AddConstructionDetail(Detail detail)
{
base.AddEquipmentDetail(detail, "aircraft");
}
}
//космический корабль
public class Spaceship : MilitaryEquipment
{
public void Shoot()
{
System.Console.WriteLine("Spaceship shoots!");
}

public void AddConstructionDetail(Detail detail)
{
base.AddEquipmentDetail(detail,"spaceship");
}
}

#endregion

public class MilitaryEquipmentFactory $16$
{
public MilitaryEquipmentFactory(IMilitaryEquipmentFactory factory)
{
IMilitaryEquipment equipment = factory.CreateEquipment();
equipment.Shoot();
}
}

public class FactoryBuilder
{
//Первый пример фабричного метода
static IMilitaryEquipmentFactory CreateFactoryMethod(int factoryNumber)
{
switch (factoryNumber)
{
case 1:
return new PanzerFactory();
case 2:
return new AircraftFactory();
case 3:
return new SpaceshipFactory();
default:
return new PanzerFactory();
}
}

//Это для теста на консоли
//static void Main(int[] args)
//{
// new Application(CreateSpecificFactory(args[0]));
// Console.ReadLine();
//}
}
}

Сказки о Design Patterns

Previous post Next post
Up