2008-11-27 5 views
3

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

Document doc = mytemplate.GetNewDoc(); 

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

Document doc = New Document(TemplateID) 

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

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

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

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

Пример из более сложного кода:

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; 
    } 
} 
} 

ответ

7

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

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

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

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

2

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

public class Factory { 
    public static Document createBlankDocument(); 
    public static Document createDocument(DocumentId id); 
    public static Document createDocumentFromTemplate(TemplateId id); 
} 
0

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

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

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

+0

Как часто это действительно выгодно для вызывающего, чтобы иметь * компилятор-принудительный * гарантировать, что `new Fizzle` вернет новый экземпляр` Fizzle ' `, а не переработанный экземпляр` Fizzle` или экземпляр некоторого производного класса или `null`? Я подозреваю, что основная причина, по которой люди используют публичные конструкторы, заключается в том, что если для построения `Fizzle` требуется один параметр типа` string`, более удобно объявлять конструктор `public`, который принимает одну строку, чем для определения` protected`, а также метод public, который его вызывает. – supercat 2012-10-25 20:11:30