Вместо того, чтобы использовать Map
хранить свойство действия (name
и nextAction
), создать свой собственный тип, состоящий из этих свойств:
class Action {
private String name;
//nextAction
public void perform() {
//do current action
//use nextAction to perform the next action
}
}
nextAction
теперь может быть ссылкой на Следующее действие:
abstract class Action implements Action {
private String name;
private Action nextAction;
public Action(String name) {
this.name = name;
}
public final void perform() {
perform(name);
nextAction.perform();
}
protected abstract void perform(String name);
}
Теперь вы можете создавать свои действия, подтипов в Action
класс:
class CreateFirstName extends Action {
public CreateFirstName(Action nextAction) {
super("CreateFirstName", nextAction);
}
protected final void perform(String name) {
System.out.println("Performing " + name);
}
}
и цепь их вместе:
Action action = new CreateFirstName(new CreateLastName(new CreateEmail(...)));
Вложенные выражения могут получить довольно грязно, но мы вернемся к этому позже. Здесь есть большая проблема.
действий4 не имеет nextAction, потому что это последнее действие, но может быть проще просто дать ему nextAction, который является заполнителем для следующего действия не
Та же проблема относится и к код выше.
Прямо сейчас, каждое действие должно выполнить следующее действие, из-за конструктора Action(String, Action)
. Мы могли бы взять легкий маршрут и пройти в качестве заполнителя для не следующего действия (null
будучи самый простой путь):
class End extends Action {
public End() {
super("", null);
}
}
И сделать нулевой чек:
//class Action
public void perform() {
perform(name);
if(nextAction != null) {
nextAction.perform(); //performs next action
}
}
Но это было бы code smell. Вы можете прекратить чтение здесь и использовать простое исправление, или продолжить ниже для более привлекательного (и образовательного) маршрута.
Существует хорошая вероятность, что, когда вы используете нуль, вы становитесь жертвой запаха кода. Хотя это не относится ко всем случаям (из-за плохой нулевой безопасности Java), вы должны попробовать avoid null if possible. Вместо этого переосмыслите свой дизайн, как в этом примере. Если все остальное не работает, используйте Optional
.
Последнее действие не совпадает с другими действиями. Он может работать как другой, но имеет разные требования к свойствам.
Это означает, что они могут как одни и те же поведение абстракции, но должны отличаться, когда речь идет об определении свойств:
interface Action {
void perform();
}
abstract class ContinuousAction implements Action {
private String name;
private Action nextAction;
public ContinuousAction(String name) {
this.name = name;
}
public final void perform() {
perform(name);
nextAction.perform();
}
protected abstract void perform(String name);
}
abstract class PlainAction implements Action {
private String name;
public PlainAction(String name) {
this.name = name;
}
public final void perform() {
perform(name);
}
protected abstract void perform(String name);
}
Последнее действие будет распространяться PlainAction
, в то время как другие будут распространяться ContinuousAction
.
Наконец, чтобы предотвратить длинные цепи:
new First(new Second(new Third(new Fourth(new Fifth(new Sixth(new Seventh(new Eighth(new Ninth(new Tenth())))))))))
Вы можете указать следующее действие в каждом конкретном действии:
class CreateFirstName extends ContinuousAction {
public CreateFirstName() {
super("CreateFirstName", new CreateLastName());
}
//...
}
class CreateLastName extends ContinuousAction {
public CreateLastName() {
super("CreateLastName", new CreateEmail());
}
//...
}
class CreateEmail extends PlainAction {
public CreateEmail() {
super("CreateEmail");
}
//...
}
ContinuousAction
и PlainAction
можно абстрагировать дальше. Они оба названных действия (у них есть имена), и это свойство влияет на их contract в samw пути (передавая его template methodprocess(String)
):
abstract class NamedAction implements Action {
private String name;
public NamedAction(String name) {
this.name = name;
}
public final void perform() {
perform(name);
}
protected abstract void perform(String name);
}
//class ContinuousAction extends NamedAction
//class PlainAction extends NamedAction
Почему просто не имеют '' List, содержащий 'CreateFirstName, CreateLastName, CreateAddress, CreateEmail'? Или 'Map ', где ключ является значением 'name', а значением является' nextAction'? –
oops. Это была опечатка. NextAction для CreateLastName должен быть CreateEmail. – Nadeemm
Обновлено. Нет createEmailName. – Nadeemm