Доброго дня!
Два вопроса к опытным коллегам:
1. Насколько корректно применение шаблона проектирования "Стратегия" для решения CrUD-задач (не конкретной данной task17.task1711 а подобного класса задач в принципе) и, самое главное, насколько адекватно он в данном случае реализован?
2. Как принято комментировать подобные решения? Если я достаточно очевидно реализую паттерн "Стратегия", нужно ли комментировать что в данной конкретной имплементации содержит контекст и что делает екзекьютор конкретной стратегии?
Поскольку, я не могу прикрепить к вопросу код решения моей задачи, так как она уже решена, пришлось состряпать портянку из вложенных классов, а т.к. публиковать правильные решения запрещено, ловите валидную с точки зрения компилятора реализацию с парой неочевидных багов, которые гарантированно не пропустит валидатор:
package com.javarush.task.task17.task1711;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Strategy interface for concrete strategies implementations
*/
interface Strategy {
/**
* Strategy executor for concrete strategies implementations
*/
void execute();
}
/**
* Context class holding concrete strategy instance
*/
class Context {
private Strategy strategy;
/**
* Class constructor specifying concrete strategy to execute.
*
* @param strategy concrete strategy instance
*/
public Context(Strategy strategy) {
this.strategy = strategy;
}
/**
* Method launching concrete strategy execution
*/
public void execute() {
strategy.execute();
}
}
/**
* Common strategy template
*/
class TemplateStrategy implements Strategy {
protected String[] params;
protected List<Person> personList;
/**
* Empty Strategy executor
*/
@Override
public void execute() {
//do nothing
}
/**
* Template strategy constructor specifying operation parameters and person list instance to operate.
*
* @param params
* @param personList
*/
public TemplateStrategy(String[] params, List<Person> personList) {
this.params = params;
this.personList = personList;
}
}
/**
* Concrete strategy for adding persons to list.
*/
class CreateStrategy extends TemplateStrategy implements Strategy {
public CreateStrategy(String[] params, List<Person> personList) {
super(params, personList);
}
/**
* Create strategy executor.
* Adds all people with assigned parameters to people list end,
* prints id (index) in the console in corresponding order
*/
@Override
public void execute() {
synchronized (personList) {
for (int i = 0; i < params.length; i += 3) {
try {
Date date = new SimpleDateFormat("dd/MM/yyyy").parse(params[i + 2]);
switch (params[i + 1].toLowerCase()) {
case "м":
personList.add(Person.createMale(params[i], date));
break;
case "ж":
personList.add(Person.createFemale(params[i], date));
break;
}
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(personList.size() - 1);
}
}
}
}
/**
* Concrete strategy for updating person data in the list.
*/
class UpdateStrategy extends TemplateStrategy implements Strategy {
public UpdateStrategy(String[] params, List<Person> personList) {
super(params, personList);
}
/**
* Update strategy executor.
* Updates corresponding data of person with defined id
*/
@Override
public void execute() {
synchronized (personList) {
for (int i = 0; i < params.length; i += 4) {
int idx = Integer.parseInt(params[i]);
Person person = personList.get(idx);
person.setName(params[i + 1]);
Sex sex;
switch (params[i + 2].toLowerCase()) {
case "м":
sex = MALE;
break;
case "ж":
sex = FEMALE;
break;
default:
sex = null;
break;
}
person.setSex(sex);
try {
person.setBirthDate(new SimpleDateFormat("dd/MM/yyyy").parse(params[i + 3]));
} catch (ParseException e) {
e.printStackTrace();
}
}
}
}
}
/**
* Concrete strategy for logical deleting persons data.
*/
class DeleteStrategy extends TemplateStrategy implements Strategy {
public DeleteStrategy(String[] params, List<Person> personList) {
super(params, personList);
}
/**
* Delete strategy executor.
* Provides logical deleting person with defined id,
* replaces all its data with null
*/
@Override
public void execute() {
synchronized (personList) {
for (int i = 0; i < params.length; i++) {
Person person = personList.get(i);
person.setName(null);
person.setSex(null);
person.setBirthDate(null);
}
}
}
}
/**
* Concrete strategy for providing information about person with defined id.
*/
class InfoStrategy extends TemplateStrategy implements Strategy {
public InfoStrategy(String[] params, List<Person> personList) {
super(params, personList);
}
/**
* Info strategy executor.
* prints in the console following data about person:
* name sex and birth date (format: 15-Apr-1990),
* id is corresponding to the index of element in list
*/
@Override
public void execute() {
synchronized (personList) {
for (int i = 0; i < params.length; i++) {
Person person = personList.get(i);
String sex;
switch (person.getSex()) {
case MALE:
sex = "м";
break;
case FEMALE:
sex = "ж";
break;
default:
sex = null;
break;
}
System.out.println(
person.getName() + " " + sex + " " +
new SimpleDateFormat("dd-MMM-yyyy", Locale.ENGLISH).format(person.getBirthDate())
);
}
}
}
}
/**
* Concrete strategy for default behaviour.
*/
class DefaultStrategy implements Strategy {
/**
* Empty Strategy executor
*/
@Override
public void execute() {
//do nothing
}
}
public class Solution {
public static volatile List<Person> allPeople = new ArrayList<Person>();
static {
allPeople.add(Person.createMale("Иванов Иван", new Date())); //сегодня родился id=0
allPeople.add(Person.createMale("Петров Петр", new Date())); //сегодня родился id=1
}
public static void main(String[] args) {
if (Objects.isNull(args) || 0 == args.length) {
return;
}
Context context;
String[] params = new String[args.length - 1];
for (int i = 0; i < params.length; i++) {
params[i] = args[i + 1];
}
switch (args[0]) {
case "-c":
//unnecessary syncronized block, just for passing validator
synchronized (allPeople) {
context = new Context(new CreateStrategy(params, allPeople));
}
break;
case "-u":
//unnecessary syncronized block, just for passing validator
synchronized (allPeople) {
context = new Context(new UpdateStrategy(params, allPeople));
}
break;
case "-d":
//unnecessary syncronized block, just for passing validator
synchronized (allPeople) {
context = new Context(new DeleteStrategy(params, allPeople));
}
break;
case "-i":
//unnecessary syncronized block, just for passing validator
synchronized (allPeople) {
context = new Context(new InfoStrategy(params, allPeople));
}
break;
default:
//unnecessary syncronized block, just for passing validator
synchronized (allPeople) {
context = new Context(new DefaultStrategy());
}
break;
}
//necessary syncronized blocks are in concrete strategy implementations
context.execute();
}
}