Каков лучший класс класса С# для работы с read + write и readonly
Я рассматриваю два разных класса для обработки ситуации, когда некоторые репозитории доступны только для чтения, а другие - для чтения-записи. (Я не вижу необходимости в репозитории только для записи.)
Дизайн классов 1 - предоставить всю функциональность в базовом классе, а затем публично публиковать применимые функциональные возможности в подклассах
public abstract class RepositoryBase
{
protected virtual void SelectBase() { // implementation... }
protected virtual void InsertBase() { // implementation... }
protected virtual void UpdateBase() { // implementation... }
protected virtual void DeleteBase() { // implementation... }
}
public class ReadOnlyRepository : RepositoryBase
{
public void Select() { SelectBase(); }
}
public class ReadWriteRepository : RepositoryBase
{
public void Select() { SelectBase(); }
public void Insert() { InsertBase(); }
public void Update() { UpdateBase(); }
public void Delete() { DeleteBase(); }
}
Class Design 2 - класс чтения-записи наследуется от класса только для чтения
public class ReadOnlyRepository
{
public void Select() { // implementation... }
}
public class ReadWriteRepository : ReadOnlyRepository
{
public void Insert() { // implementation... }
public void Update() { // implementation... }
public void Delete() { // implementation... }
}
Является ли один из этих проектов более сильным, чем другой? Если да, то какой и почему?
P.S. Если это звучит как вопрос о домашнем задании, это не так, но вы можете использовать его как один, если хотите:)
Ответы
Ответ 1
Как насчет третьего варианта, тесно связанного с первым, но используя вместо него интерфейсы:
public interface IReadRepository {
public void Select();
}
public interface IWriteRepository {
public void Insert();
public void Update();
public void Delete();
}
// Optional
public interface IRepository : IReadRepository, IWriteRepository {
}
public class Repository : IRepository {
// Implementation
}
Таким образом, реализация (или может быть) реализована в одном месте, а различие выполняется только с помощью интерфейса, на который вы смотрите.
Ответ 2
( Изменить: Я думаю, что Eric Petroelje предлагает очень приятное решение на основе интерфейса в своем ответе. Вероятно, я проголосовал бы за его предложение, прежде всего.)
Из ваших двух вариантов я бы четко проголосовал за дизайн # 2.
С дизайном №1 я думаю, что нет смысла иметь класс "только для чтения", который внутренне не доступен только для чтения:
-
Класс только для чтения "тяжелее", чем должен быть.
-
Любой может быть получен из вашего класса только для чтения, а затем вызывать любые методы модификации базового класса. По крайней мере, с дизайном №1, вы должны сделать класс только для чтения sealed
.
С дизайном №2 он намного яснее, чем класс только для чтения, это уменьшенная версия (базовый класс) полнофункционального класса или выраженная иначе.
Ответ 3
Сначала позвольте мне признать, что я делаю некоторые предположения о том, что вы могли бы сделать. Если это пропустит точку, тогда дайте мне знать.
Я не уверен, насколько полезны классы в любом из двух ваших вариантов. Я предполагаю, что у вас будет код вызова, который будет использовать экземпляр репозитория для чтения, а в другом случае - экземпляр репозитория чтения/записи, но интерфейсы не совпадают, так что вы все равно должны отличаться в своем коде?
Лучше всего предоставить общий интерфейс, а затем бросить исключения, если вы попытаетесь записать в репозиторий, когда он будет readony, а ваш код обработает исключения.
Ответ 4
Я бы сказал, дизайн # 2, но тогда вы должны изменить имя ReadOnlyRepository на что-то вроде ReadRepository.
Наследование определяет отношение IS-A между классами, а an говорит, что "ReadWriteRepository - это ReadOnlyRepository" не звучит логично. Но "ReadWriteRepository - это ReadingRepository" делает.
Ответ 5
Я бы сказал, что дизайн 2 самый сильный. Если вы хотите иметь реализацию только для чтения, ему не нужно ничего знать о написании. Имеет смысл расширить реализацию только для чтения с помощью методов вставки, обновления и удаления. Я также думаю, что этот дизайн является тем, который наиболее соответствует принципу Open-Closed.
Ответ 6
Я бы предложил иметь базовый класс ReadableFoo с запечатанным производным классом ImmutableFoo, чей конструктор принимает ReadableFoo и возможно наследуемый производный класс MutableFoo и, возможно, класс ReadableShadowFoo, конструктор которого примет ReadableFoo (который может или не может быть изменчивым), но который будет действовать как обертка только для чтения.
Ответ 7
Ответ Эрика означает SOLID-принцип ISP. Это так просто и удобно использовать.