Обычно в этом коде нет ничего плохого, пока он не распространился по вашей кодовой базе.В этом случае лучше провести рефакторинг как-то.
Естественный ООП способ сделать это - добавить виртуальный метод Save
в класс Person
и переопределить его во всех потомках.Но мы, очевидно, будем нарушать несколько принципов проектирования, делая это.
По этой причине существует шаблон Visitor , который позволяет добавлять пользовательские операции в существующую структуру данных.
Это может быть реализовано таким образом для вашего сценария.
public interface IPersonVisitor
{
void Visit(Person person);
void Visit(Employee employee);
void Visit(Customer customer);
/*Visit method overload for every item in hierarchy*/
}
Метод, принимающий посетителя в базовом классе иерархии
public class Person
{
public string Name;
public virtual void Accept(IPersonVisitor visitor)
{
visitor.Visit(this);
}
}
Переопределяется во всех потомках
public class Employee : Person
{
public int EmployeeID;
public override void Accept(IPersonVisitor visitor)
{
visitor.Visit(this);
}
}
И фактическая реализация операции для каждого типа
public class DaoPersonVisitor: IPersonVisitor
{
public void Visit(Person person)
{
var personDao = new PersonDao();
personDao.Save(person);
}
public void Visit(Employee employee)
{
var employeeDao = new EmployeeDao();
employeeDao.Save(employee);
}
public void Visit(Customer customer)
{
var customerDao = new CustomerDao();
customerDao.Save(customer);
}
}
Тогда вы могли бы назвать это следующим образом
var person = new Employee();
person.Accept(new DaoPersonVisitor());
Разрешение перегрузки сыграет свою роль и DaoPersonVisitor.Visit(Emploee)
будет вызван.
Посетитель хорошо подходит, когда мы хотим добавить какую-то конкретную операцию в иерархию, но это выглядит излишним для вашего случая, потому что сам посетитель не содержит какой-либо конкретной логики - выбираетсоответствующий объект DAO и ничего более.
Вероятно, будет достаточно переместить логику выбора DAO в одно место, поскольку это удалит все дубликаты.
Вам потребуется интерфейс или базовый класс для вашегоТипы DAO, реализующие его во всех потомках.
public interface IPersonDao
{
void Save(Person person);
}
И фабричный класс (или просто метод, если эта логика может быть помещена в некоторые границы классов)который возвращает соответствующий DAO
public static class PersonDaoFactory
{
public static IPersonDao Create(Person person)
{
if (person is Employee)
{
return new EmployeeDao();
}
if (person is Customer)
{
return new CustomerDao();
}
/* cases for all the other object in hierarchy */
throw new NotSupportedException($"Can't create DAO for '{person.GetType().FullName}'. Type is not supported.");
}
}
Тогда вы можете просто вызывать этот метод во всех местах, где DAO следует выбирать в зависимости от типа человека - это означает, что дублирования нет.