So I am trying to code to an interface rather than an implementation. So I have a factory that return开发者_开发知识库s an object that derives from Employee. So these objects may be something like Developer : Employee, Secretary : Employee, etc.
So I put all of the shared properties like FirstName, LastName, Email, etc. in the base class (Employee).
And I should put all of the properties specific to each type in just that type. So Developer would have some properties in it like Skills, ProgrammingLanguages, etc. but then I will not be able to access these properties from the Employee object unless I use the concrete type of Developer.
e.g.
Employee employee = new EmployeeFactory.CreateEmployee(EmployeeType.Developer);
employee.ProgrammingLanguages = "C#, Java, C++"; <-- compile error
What's the best way to go about this? Reflection...?
Why bother with a factory if you're going to be explicitly saying what type of employee to use?
Instead, you can just write:
Developer dev = new Developer();
dev.ProgrammingLanguages = "C#, Java, C++"; // compiles fine
Later, you can still add the "developer" to a list of employees, ie:
IList<Employee> theEmployees = GetEmployees();
theEmployees.Add(dev); // This is fine, since Developer is an Employee...
Why not use generics and have something like
T EmployeeFactory.CreateEmployee<T>()
{
return new T();
}
And call it like
var dev = EmployeeFactory.CreateEmployee<Developer>();
That way you would end up with a typed Developer.
In your code, clearly when you try to do employee.ProgrammingLanguages
you know that employee
is of type Developer
. So you can just cast to that:
Developer dev = new (Developer)EmployeeFactory.CreateEmployee(EmployeeType.Developer);
dev.ProgrammingLanguages = "C#, Java, C++";
Or more perhaps:
Developer dev = new Developer(); // If you don't really need the factory.
dev.ProgrammingLanguages = "C#, Java, C++";
In contexts where you don't know if this can be done or not, you can test with is
or as
.
Keep things at the level they make sense to deal with them at. Clearly it doesn't make sense to talk about the programming languages of someone who might not program, so its fine to work at the Developer
level of the hierarchy. Code for dealing with holidays and salary should either be the same for all employees, or at least work through a common interface with the possibility of overrides, and so it would work at the Employee
level of the hierarchy.
It seems to me like, at least in this specific case, you shouldn't be using the base type.
You're working with something specific to a Developer
rather than a generic Employee
so you lose the benefit of working with the base type. In this case, just create a new developer:
Developer developer = new Developer();
developer.ProgrammingLanguages = "C#, Java, C++";
That being said, you could always try a cast back to the more specific type:
Employee employee = new EmployeeFactory.CreateEmployee(EmployeeType.Developer);
Developer developer = employee as Developer;
if(developer != null) developer.ProgrammingLanguages = "C#, Java, C++";
In this case I would suggest using the simpliest solution. Create one method per one employee type, like this:
public Developer CreateDeveloper();
public Secretary CreateSecretary();
Why this "ugly" solution? Because you need to know the type in the client code either way. So why to complicate with generics/reflection? Simpicity is divine.
精彩评论