Dichiarazione di problemi: scrivi un programma per costruire una casa, la casa può essere dei seguenti tipi: Appartamento, Casa individuale, Bungalow. La cucina è personalizzabile: Cucina italiana, Cucina modulare, Cucina standard; No di camere da letto è personalizzabile: OneBedroom, TwoBedroom, ThreeBedroom; La Drawingroom è personalizzabile: StandardDrawingRoom, BalconyFacingDrawingRoom
Ecco le classi e l'interfaccia che ho messo insieme. Ecco alcune delle cose che vorrei sapere:
- Lo chiamerai modello di fabbrica astratto o modello di fabbrica?
- Vedi qualche problema con il design qui?
- Quali miglioramenti possono essere apportati in questo design?
Casa:
interface IHouse
{
void BuildHouse(IKitchen kitchen, IDrawingRoom drawingRoom, IBedroom bedRoom);
}
class Apartment : IHouse
{
public void BuildHouse(IKitchen kitchen, IDrawingRoom drawingRoom, IBedroom bedRoom)
{
Console.WriteLine("Building Apartment");
drawingRoom.BuildDrawingRoom();
bedRoom.BuildBedroom();
kitchen.BuildKitchen();
}
}
class IndividualHouse : IHouse
{
public void BuildHouse(IKitchen kitchen, IDrawingRoom drawingRoom, IBedroom bedRoom)
{
Console.WriteLine("Building IndividualHouse");
drawingRoom.BuildDrawingRoom();
bedRoom.BuildBedroom();
kitchen.BuildKitchen();
}
}
class Bungalow : IHouse
{
public void BuildHouse(IKitchen kitchen, IDrawingRoom drawingRoom, IBedroom bedRoom)
{
Console.WriteLine("Building Bungalow");
drawingRoom.BuildDrawingRoom();
bedRoom.BuildBedroom();
kitchen.BuildKitchen();
}
}
Cucina:
interface IKitchen
{
void BuildKitchen();
}
class ItalianKitchen : IKitchen
{
public void BuildKitchen()
{
Console.WriteLine("Italian Kitchen Built");
}
}
class StandardKitchen : IKitchen
{
public void BuildKitchen()
{
Console.WriteLine("Standard Kitchen Built");
}
}
class ModularKitchen : IKitchen
{
public void BuildKitchen()
{
Console.WriteLine("Modular Kitchen Built");
}
}
camera da letto:
interface IBedroom
{
void BuildBedroom();
}
class OneBedroom : IBedroom
{
public void BuildBedroom()
{
Console.WriteLine("One Bedroom Built");
}
}
class ThreeBedroom : IBedroom
{
public void BuildBedroom()
{
Console.WriteLine("Three Bedroom Built");
}
}
class TwoBedroom : IBedroom
{
public void BuildBedroom()
{
Console.WriteLine("Two Bedroom Built");
}
}
Salotto:
interface IDrawingRoom
{
void BuildDrawingRoom();
}
class StandardDrawingRoom : IDrawingRoom
{
public void BuildDrawingRoom()
{
Console.WriteLine("Standard Drawing Room Built");
}
}
class BalconyFacingDrawingRoom : IDrawingRoom
{
public void BuildDrawingRoom()
{
Console.WriteLine("Balcony Facing Drawing Room Built");
}
}
L'input sarà un oggetto che definisce la personalizzazione:
interface IHouseDefinition
{
HouseType HouseType { get; set; }
BedroomType BedroomType { get; set; }
DrawingRoomType DrawingRoomType { get; set; }
KitchenType KitchenType { get; set; }
}
class HouseDefinition : IHouseDefinition
{
public HouseType HouseType { get; set; }
public BedroomType BedroomType { get; set; }
public DrawingRoomType DrawingRoomType { get; set; }
public KitchenType KitchenType { get; set; }
}
public enum HouseType : int
{
Apartment,
Bungalow,
IndividualHouse,
Villament
}
public enum BedroomType : int
{
OneBedroom,
TwoBedroom,
ThreeBedroom
}
public enum DrawingRoomType : int
{
BalconyFacingDrawingRoom,
StandardDrawingRoom
}
public enum KitchenType : int
{
ModularKitchen,
StandardKitchen,
ItalianKitchen
}
Ecco le classi di fabbrica che ho progettato:
interface IHouseComponentFactory<T, R> where T : class where R : IConvertible
{
T GetComponent(R type);
}
class KitchenFactory : IHouseComponentFactory<IKitchen, KitchenType>
{
public IKitchen GetComponent(KitchenType type)
{
switch (type)
{
case KitchenType.ModularKitchen:
return new ModularKitchen();
case KitchenType.StandardKitchen:
return new StandardKitchen();
case KitchenType.ItalianKitchen:
return new ItalianKitchen();
default:
throw new InvalidOperationException("Unrecognized KitchenType");
}
}
}
class BedroomFactory : IHouseComponentFactory<IBedroom, BedroomType>
{
public IBedroom GetComponent(BedroomType type)
{
switch (type)
{
case BedroomType.OneBedroom:
return new OneBedroom();
case BedroomType.TwoBedroom:
return new TwoBedroom();
case BedroomType.ThreeBedroom:
return new ThreeBedroom();
default:
throw new InvalidOperationException("Unrecognized BedroomType");
}
}
}
class DrawingRoomFactory : IHouseComponentFactory<IDrawingRoom, DrawingRoomType>
{
public IDrawingRoom GetComponent(DrawingRoomType type)
{
switch (type)
{
case DrawingRoomType.BalconyFacingDrawingRoom:
return new BalconyFacingDrawingRoom();
case DrawingRoomType.StandardDrawingRoom:
return new StandardDrawingRoom();
default:
throw new InvalidOperationException("Unrecognized DrawingRoomType");
}
}
}
interface IHouseFactory
{
IHouse GetHouse(HouseType type);
}
class HouseFactory : IHouseFactory
{
public IHouse GetHouse(HouseType type)
{
switch (type)
{
case HouseType.Apartment:
return new Apartment();
case HouseType.Bungalow:
return new Bungalow();
case HouseType.IndividualHouse:
return new IndividualHouse();
default:
throw new InvalidOperationException("Unrecognized HouseType");
}
}
}
Ecco l'assemblatore di fabbrica e l'HouseBuilder (una classe di supporto):
class HouseFactoryAssembler
{
private IHouseComponentFactory<IKitchen, KitchenType> m_KitchenFactory;
private IHouseComponentFactory<IBedroom, BedroomType> m_BedroomFactory;
private IHouseComponentFactory<IDrawingRoom, DrawingRoomType> m_DrawingRoomFactory;
private IHouseFactory m_HouseFactory;
public static HouseFactoryAssembler Instance = new HouseFactoryAssembler();
private HouseFactoryAssembler()
{
m_KitchenFactory = new KitchenFactory();
m_BedroomFactory = new BedroomFactory();
m_DrawingRoomFactory = new DrawingRoomFactory();
m_HouseFactory = new HouseFactory();
}
public IHouseFactory HouseFactory
{
get { return m_HouseFactory; }
}
public IHouseComponentFactory<IKitchen, KitchenType> KitchenFactory
{
get { return m_KitchenFactory; }
}
public IHouseComponentFactory<IBedroom, BedroomType> BedroomFactory
{
get { return m_BedroomFactory; }
}
public IHouseComponentFactory<IDrawingRoom, DrawingRoomType> DrawingRoomFactory
{
get { return m_DrawingRoomFactory; }
}
}
class HouseBuilder
{
public static void BuildHouse(IHouseDefinition houseDefinition)
{
IKitchen kitchen = HouseFactoryAssembler.Instance.KitchenFactory.GetComponent(houseDefinition.KitchenType);
IBedroom bedroom = HouseFactoryAssembler.Instance.BedroomFactory.GetComponent(houseDefinition.BedroomType);
IDrawingRoom drawingRoom = HouseFactoryAssembler.Instance.DrawingRoomFactory.GetComponent(houseDefinition.DrawingRoomType);
IHouse house = HouseFactoryAssembler.Instance.HouseFactory.GetHouse(houseDefinition.HouseType);
house.BuildHouse(kitchen, drawingRoom, bedroom);
}
}