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