What Design Pattern Should I use to accomplish the task below
I need 开发者_如何学运维to be able to conditionally execute a method. I prefer not having a bunch of IF statements throughout my code for several reasons, the most notable is that at a certain point in the future the method will no longer be used.
I am not sure of the best way to do this or what pattern(s) I should choose to accomplish this task.
The application I refer to is an application that is going to replace a legacy system. The legacy code will be turned off and no longer used at some point. Once that point of time comes, I don't want to have to go back and change any code (if at all possible).
The following is a fictious conceptual example in psuedo of what I mean:
NewSystemEmployee.Save(Employee e)
if (Legacy System Is Running)
{
LegacySystemEmployee.Save(Employee e)
}
The method NewSystemEmployee.Save
always needs to execute. I only want to execute LegacySystemEmployee.Save
as long as the Legacy system is running. Once the Legacy system is shutdown, I no longer want to execute LegacySystemEmployee.Save
Once the legacy system goes away, I don't know how I can accomplish what I want without:
- Creating an IF statement before I call
LegacySystemEmployee.Save
OR - Removing every call to
LegacySystemEmployee.Save
method OR - Changing
LegacySystemEmployee.Save
method so that it is a stub and nothing more
I also have a requirement that the NewSystemEmployee
class does not refer in any way to the LegacySystemEmployee
class.
Any suggestions?
Thanks so much
At first glance this calls for the Strategy pattern (or in fact Template Method), possibly with a Factory Method to control which strategy to use. Example (in pseudo-Java):
class Saver {
protected void LegacySave(Employee e) {}
public final void Save(Employee e) {
NewSystemEmployee.Save(e);
LegacySave(e);
}
}
class LegacySaver extends Saver {
protected void LegacySave(Employee e) {
LegacySystemEmployee.Save(e);
}
}
Since at some point in time you will no more need the legacy call, it makes sense to implement the default LegacySave
as empty. Then you can trivially use the class like this:
getSaver().save(employee);
where getSaver()
is the factory method which silently decides which Saver
implementation to present to its caller. Trivially it can get the class name from a config file.
Question is, how do you need to change the behaviour: runtime, or by restarting the application? If you can restart the application, it is easy to change that one line in the configuration which controls the strategy to use. Changing behaviour on-the-fly is slightly more tricky, but doable.
A lot depends on what programming language you use. E.g. in Java / C++ / C# you can easily accomplish what you want with dependency injection; in some other languages it might not be that easy.
I would suggest either the Strategy Pattern, or the Template Method Pattern.
Some links:
Strategy pattern - Wikipedia Article
Strategy Pattern - SourceMaking Website - includes some great examples.
Template Method - Wikipedia Article
Template Method - SourceMaking Website
Aspects will help you, you can inject some behavior before/after your method from external code. Don't know what technology you work in, so you need to look for suitable implementation of AOP on your own.
I think that the most appropriate pattern to your situation is a combination of strategy design pattern & factory method design pattern
In your code, don't reffer to the legacy/new algorithm, but to the strategy interface. You will retrieve the interface using the factory method you have.
If you are using Java/C#, you can use IoC tool, like Unity or spring instead/ in addition to your factory
I'd go with simple proxy that looks like the legacy system, but checks whether it's running and delegates the action to it in that case:
class LegacySystemEmployeeProxy {
public Save(Employee employee) {
if (Legacy System Is Running) {
LegacySystemEmployee.Save(employee)
}
}
}
Now your original code reduces to:
NewSystemEmployee.Save(employee)
LegacySystemEmployeeProxy.Save(employee)
When the legacy system goes away, you can change LegacySystemEmployeeProxy.Save to an empty method.
Well two solutions come immediately to my mind:
- Use conditional comppillation if that is available, e.g. (C#)
#if (legacy)
LegacySystemEmployee.Save(Employee e)
#endif
- Create a new method SaveEmployee, e.g. (c#)
public static SaveEmployee(Employee e) {
NewSystemEmployee.Save(Employee e)
if (Legacy System Is Running) { LegacySystemEmployee.Save(Employee e) }
}
In extension to that you could create a "service interface" that encapsulates all methods that call both systems. And obviously you could combine methods into one, e.g. (C#)
public static SaveEmployee(Employee e) {
NewSystemEmployee.Save(Employee e)
#if (legacy)
LegacySystemEmployee.Save(Employee e)
#endif
}
In order for the conitional code to be active you must define the legacy identifier either using
#define legacy
or as a conditional compilation symbol during the complilation.
精彩评论