Позвоните на фабрику из конструктора, чтобы получить новую версию "этого" - PullRequest
3 голосов
/ 27 ноября 2008

Я могу идти об этом задом наперед ... У меня есть класс, который похож на документ, и другой класс, который похож на шаблон. Они оба наследуются от одного и того же базового класса, и у меня есть метод для создания нового документа из шаблона (или из другого документа, метод, который находится в базовом классе). Итак, если я хочу создать новый документ из шаблона, я просто создаю экземпляр шаблона и вызываю GetNewDoc () для него;

Document doc = mytemplate.GetNewDoc();

В классе Document у меня есть пустой конструктор, создающий новый пустой документ, а также другой конструктор, который принимает идентификатор документа, чтобы я мог загрузить документ из базы данных. Тем не менее, я также хотел бы конструктор, который принимает идентификатор шаблона. Таким образом, я могу сделать

Document doc = New Document(TemplateID)

Поскольку класс шаблона уже имеет возможность возвращать документ, я бы хотел, чтобы конструктор сделал что-то вроде

Template temp = new Template(TemplateID);
this = temp.GetNewDoc();

Конечно, я не могу этого сделать, поскольку "this" доступно только для чтения - и в любом случае это кажется странным. У меня такое чувство, что я очень глупый, поэтому не стесняйтесь кричать:)

Дело в том, что рассматриваемый объект является довольно сложным с несколькими коллекциями дочерних объектов и сохранением базы данных в нескольких таблицах, поэтому я не хочу дублировать слишком много кода. Хотя, я думаю, я мог бы просто получить новый документ из шаблона и затем скопировать поля / свойства, так как коллекции должны следовать достаточно легко - это просто похоже на дублирование.

Более сложный пример кода:

</p> <pre><code>using System; using System.Collections.Generic; using System.Text; namespace Test { class Program { static void Main(string[] args) { // This just creates the object and assigns a value Instance inst = new Instance(); inst.name = "Manually created"; Console.WriteLine("Direct: {0}", inst.name); //This creates a new instance directly from a template MyTemplate def = new MyTemplate(); Instance inst2 = def.GetInstance(100); Console.WriteLine("Direct from template: {0}", inst2.name); Instance inst3 = new Instance(101); Console.WriteLine("Constructor called the template: {0}", inst3.name); Console.ReadKey(); } } public class Instance { public string name; public Instance(int TemplateID) { MyTemplate def = new MyTemplate(); //If I uncomment this line the build will fail //this = def.GetInstance(TemplateID); } public Instance() { } } class MyTemplate { public Instance GetInstance(int TemplateID) { Instance inst = new Instance(); //Find the template in the DB and get some values inst.name = String.Format("From template: {0}", TemplateID.ToString()); return inst; } } }

Ответы [ 3 ]

7 голосов
/ 27 ноября 2008

Если вы хотите иметь возможность делать что-то кроме создания нового объекта только из кода в конструкторе, не используйте конструктор в первую очередь.

Вам действительно нужен конструктор Instance, принимающий int? Почему бы не превратить его в статический фабричный метод:

public static Instance CreateInstance(int id)
{
    MyTemplate def = new MyTemplate();
    return def.GetInstance(id);
}

Статические методы имеют различные преимущества перед конструкторами - хотя и некоторые недостатки тоже. (На этот вопрос есть отдельный вопрос - стоит посмотреть.)

2 голосов
/ 27 ноября 2008

Вы не можете воссоздать 'this' ни из конструктора, ни из любого другого метода. Вы можете создать другой объект и скопировать содержимое, но я бы сделал фабрику общедоступной. Определите фабричный класс, имеющий три метода createDocument (), один для пустого документа, один для документа из БД и третий для шаблона:

public class Factory {
   public static Document createBlankDocument();
   public static Document createDocument( DocumentId id );
   public static Document createDocumentFromTemplate( TemplateId id );
}
0 голосов
/ 27 ноября 2008

Я с Джоном, гораздо лучше использовать фабричные методы, так как это совершенно ясно для разработчика о том, что происходит (что-то больше , чем просто создание нового объекта).

Заводской метод говорит программисту: «Здесь происходит какая-то особая инициализация, когда использование new не будет достаточно хорошим».

Как правило, вы будете использовать фабрики, когда хотите перерабатывать или кэшировать ресурсы, и, наоборот, вы не ожидаете использования переработанных или кэшированных ресурсов при использовании ключевого слова new ; вы ожидаете новый ресурс (он запечатлен прямо в ключевом слове):)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...