Допустим есть вот такая реализация фабричного метода:
abstract class Creator
{
public abstract Product FactoryMethod();
}
class ConcreteCreatorA : Creator
{
public override Product FactoryMethod() { return new ConcreteProductA(); }
}
abstract class Product
{}
class ConcreteProductA : Product
{}
Какая выгода нам от создания объекта через Creator, если точно так же можно его создать через new? Когда нужно использовать именно фабричный метод, и какое преимущество нам это может дать?
Ответ
Выгод может быть много. Некоторые:
Вы можете дать имя вашему конструктору. Например:
Point PointCreator.FromPolar(double r, double phi)
PointCreator.FromPolar читается намного лучше, чем new Point(1, 0)
Раз уж вы даёте имя, вы можете иметь несколько конструкторов с одинаковыми сигнатурами:
Point PointCreator.FromPolar(double r, double phi) { ... }
Point PointCreator.FromCartesian(double x, double y) { ... }
или например
DateTime DateTime.FromSeconds(double seconds) { ... }
DateTime DateTime.FromMilliseconds(double ms) { ... }
Вы можете создавать объекты не данного типа, а любого производного, причём конкретный тип может быть скрыт внутри фабрики (так что у вашего остального кода не будет зависимости от этого конкретного типа).
Вы можете сделать дополнительные действия после окончательного построения объекта. Например, вы можете зарегистрировать объект в списке всех активных объектов. С конструктором такое не очень удобно, т. к. вам придётся делать это либо в конструкторе базового класса, и выкладывать ссылку на недоконструированный объект (что может привести к понятным проблемам, если кто-то в этот момент обратится к объекту), либо дублировать код во всех потомках (что не всегда возможно, и непроверяемо, так что провоцирует баги).
Или вы можете сделать дополнительную инициализацию свойств объекта, если вам это нужно:
WebRequest InitWebRequest(string uri)
{
var request = WebRequest.Create(uri);
request.Credentials = new NetworkCredential(Settings.Login, Settings.Password);
return request;
}
Вы не можете сделать конструктор асинхронным, а фабричный метод — можете. В самом фабричном методе вы можете вызвать конструктор и async-метод для инициализации.
async SerialDevice Create(PortInfo portInfo)
{
var device = new SerialDevice(portInfo);
await device.Connect();
return device;
}
Комментариев нет:
Отправить комментарий