2015-07-09 7 views
2

При проектировании класса и конструкторов у меня возникает вопрос о получении записи.Конструктор классов и получение дизайна

В качестве примера, если у меня есть автомобиль класса

public Car 
{ 
    ... 
} 

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

public Car(int carID) 
{ 
    //Get car from database 
} 

Или я мог бы напишите открытый метод, чтобы получить автомобиль:

public Car GetCarByID(int carID) 
{ 
    //Get car from database 
} 

Есть ли предпочтительный (наилучший способ) метод для получения экземпляра класса? Код, кажется, читает уборщика, чтобы сделать получить экземпляр объекта:

Car MyCar = new Car(5); 

против

Car MyCar = new Car(); 
MyCar.GetCarByID(5); 
+0

В этом случае у меня будет класс под названием car, который обрабатывает всю базовую информацию. (Как и идентификатор). Тогда я бы назвал класс CarCollection, который содержит автомобили в коллекции. В этом классе у меня был бы метод GetCarById. В этом методе я бы искал коллекцию автомобилей и возвращал автомобиль с этим идентификатором. Этот вопрос очень основан на мнениях, хотя он здесь не для темы. – deathismyfriend

+0

Разделение проблем, если ваш класс 'car' действительно является классом, который содержит информацию о' car', вы должны использовать слой доступа к данным для создания объектов 'car', не требуя, чтобы' car' знал о базе данных , –

+1

Зачем автомобилю знать, как получить себя из базы данных? Ни одно из ваших предложений не является хорошим и является нарушением СРП. –

ответ

2

Я бы рекомендовал отделить доступ к базе данных от классов модели домена, таких как Car.

Это можно сделать, поместив все операции поиска доступа к базе данных в свой собственный набор классов. Они называются репозиториями. Существуют разные подходы к созданию этих репозиториев. Это зависит от того, как ваши данные хранятся в базе данных и использует ли вы инфраструктуру сущности. Некоторые предпочитают общие хранилища, тогда как другим вообще не нравится этот общий подход. Но суть в том, что репозитории заботятся о доступе к базе данных для поиска объектов и их хранения. Это не должно делаться объектом домена, то есть самим автомобилем, потому что у него должны быть только операции, принадлежащие автомобилю, и что делает его объектом Car. Хранение автомобиля в базе данных не означает, что автомобиль должен знать, как это сделать.

Пример использования шаблона хранилища можно найти здесь: http://www.codeproject.com/Articles/688929/Repository-Pattern-and-Unit-of

Существует также хорошая статья на MSDN о хранилище шаблона: https://msdn.microsoft.com/en-us/library/ff649690.aspx?f=255&MSPPError=-2147217396

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

Намного лучше, чем создавать методы в ваших классах, которые там не принадлежат.

+0

Спасибо за объяснение. Хотя это вызывает другой вопрос, если бы у меня был метод DriveCar(), который требовал получить максимальную скорость доступа к машинам из базы данных, я думаю, что метод DriveCar() будет принадлежать определению класса, тогда он будет ссылаться на класс репозитория автомобилей получить максимальную скорость? Или я думаю об этом не так? – TreK

+0

В тот момент, когда репозиторий автомобилей извлекает данные, принадлежащие автомобилю, он должен извлекать все аспекты важного автомобиля и того, что делает автомобиль автомобилем. Максимальная скорость, безусловно, является атрибутом автомобиля, поэтому да, он должен быть получен непосредственно при загрузке автомобиля из Db. Вы можете пойти еще дальше в этом направлении, выполнив проект, управляемый доменом, и используя только совокупный корень для точек входа. Но это другая тема. http://www.methodsandtools.com/archive/archive.php?id=97p2 –

1

Одно простое решение состоит в использовании static method, например, так:

public static Car GetById(int carId) 
{ 
    ... Load car and return it ... 
} 

Затем вы можете назвать это следующим образом:

Car myCar = Car.GetById(18); 
+2

Автомобиль, безусловно, не должен быть расширен такими методами. Это нарушает SRP и будет сложно провести тестирование. –

+0

О, это действительно зависит. Для небольшого проекта добавление такого статического метода может сэкономить вам время, не обойдя вас ничем. Вот почему я сказал, что это одно решение, и простой в этом. – zmbq

0

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

public class Car 
{ 
    public string Make {get; set;} 
    public string Model {get; set;} 
    // additional properties here. 
} 

public static class CarFactory 
{ 
    public static Car CreateCar(string modelId) 
    { 
     Car car = new Car(); 
     // Load the car via whatever mechanism you wish; 
     // e.g., web service, database, etc. 
     return car; 
} 

Car fordFairlane = CarFactory.CreateCar("57fordFairlane"); 

Это сохраняет код для создания объекта автомобиля отдельно от самого объекта автомобиля, и позволяет изменять как создается автомобиль, не касаясь класса автомобиля.

+0

Это не дает простой способ загрузить автомобиль по идентификатору. Это просто создает новый автомобиль с идентификатором. – deathismyfriend

+0

Код загрузки не очень важен, поэтому я не поместил много постороннего кода БД. Важно, что в этом примере показано, как сохранить код, создающий объект, из самого класса кода объекта. Отсюда комментарии после вызова конструктора. – BardMorgan

+0

Нет, в комментарии четко сказано, что вы можете загрузить автомобиль из базы данных. Добавьте способ хранения для этого так называемого «фабрики», и у вас есть репозиторий. –

2

Как я уже сказал в своем комментарии, я бы сделал это, чтобы управлять автомобилями и разрешать загрузку автомобиля по id или еще что-нибудь, что вы хотите загрузить.

public class Car 
{ 
    public int Id { get; set; } 
    public Car() { } 
    public Car(int id) { Id = id; } 
} 

public class CarCollection 
{ 
    public List<Car> Cars { get; set; } 

    public void AddCar(Car car) { Cars.Add(car); } 

    public Car GetById(int id) { return Cars.Single(x => x.Id == id); } 

    public CarCollection(List<Car> cars) { Cars = cars; } 
    public CarCollection(Car car) { Cars = new List<Car>() { car }; } 
} 
+0

Мне нравится этот пример, однако для реализации, похоже, требуется много накладных расходов. Например, чтобы получить автомобиль по идентификатору, мне сначала нужно создать экземпляр объекта Car, а затем создать объект CarCollection для заполнения объекта Car? В некоторых других примерах используются статические классы, но из моего чтения это звучит так, как статические классы не должны использоваться таким образом? – TreK

+0

Я не вижу, как это использует много накладных расходов, так как вам все равно нужно хранить все автомобили в списке/массиве/словаре/другой структуре данных. Коллекция позволяет легко получить доступ к автомобилям, которые вы хотите, не прибегая к статическим методам. В этих статических методах вам нужно будет сдать в них коллекцию автомобилей, чтобы они могли перебирать машины и выбирать нужный вам. Класс выше уже обрабатывает это. В качестве примера, если вы когда-либо использовали DataGridView, вы также заметите, что это похоже на классы RowCollection и ColumnCollection. – deathismyfriend