Die Logik für eine einzelne Entität sollte das Verhalten für die Entität definieren, aber ich bin verwirrt darüber, wo die Verarbeitung für die Liste oder den Satz von Entitäten geschrieben werden soll. Ich habe den Inhalt zusammengefasst, den ich untersucht habe, um ein solches Zögern zu lösen.
Ich habe oft die Verarbeitung für Listen und Sätze von Entitäten in Service und Controller geschrieben.
HogeController.java
@Controller
public class HogeController {
private final HogeService service;
HogeController(HogeService service) {
this.service = service;
}
@RequestMapping("hoge")
public String xxx(Model model) {
List<ShoppingCartItem> cartItems = new ArrayList<>();
Integer total = cartItems.stream().mapToInt(ShoppingCartItem::subtotal()).sum();
model.addAttribute("total", total);
return "hoge/hoge";
}
}
Ich denke das ist in Ordnung. Wenn Sie diesen Prozess jedoch in den Controller schreiben und denselben Prozess in einem anderen Controller ausführen möchten, wird der Code wahrscheinlich kopiert und die Wartung wird schwierig, wenn Änderungen an der Logik vorgenommen werden. Ist sichtbar.
Wenn Sie also eine Klasse erstellen, die eine Menge darstellt, wie unten gezeigt, können Sie die Logik an einer Stelle einschränken.
ShoppingCartItems.java
public class ShoppingCartItems {
private List<ShoppingCartItem> items = new ArrayList<>();
public void addItem(ShoppingCartItem item) {
items.add(item);
}
public Integer total() {
return items.stream().mapToInt(ShoppingCartItem::subtotal()).sum();
}
}
Jetzt haben Sie eine Methode, um den Gesamtbetrag in einer Klasse zu berechnen. Dies ist jedoch immer noch unpraktisch. Dies liegt daran, dass Sie nicht jedes ShoppingCartItem abrufen können. ~~ Hirntod ~~ Es ist in Ordnung, Getter zu definieren, aber hier sind einige nützliche Techniken.
Es gibt eine erweiterte for-Anweisung als Syntax, mit der Sie jedes ShoppingCartItem abrufen. Es wäre schön, wenn Sie es so nennen könnten!
ShoppingCartItems shoppingCartItems = new ShoppingCartItems();
for (ShoppingCardItem item : shoppingCartItems) {
// doSomething
}
Um dies zu erreichen, ist es besser, die Schnittstelle "Iterable
ShoppingCartItems.java
public class ShoppingCartItems implements Iterable<ShoppingCartItem> {
private List<ShoppingCartItem> items = new ArrayList<>();
//Kürzung
@Override
public Iterator<Asking> iterator() {
return items.iterator();
}
@Override
public void forEach(Consumer<? super Asking> action) {
items.forEach(action);
}
@Override
public Spliterator<Asking> spliterator() {
return items.spliterator();
}
}
Für die drei Methoden, die in der Iterable-Schnittstelle implementiert werden sollen, können Sie die Methode des in der Klasse enthaltenen Felds "Elemente" der Auflistungsklasse aufrufen. Jetzt können Sie eine erweiterte for-Anweisung schreiben.
Ich möchte so schreiben.
HogeController.java
@Controller
public class HogeController {
@GetMapping("hoge")
public String hoge(Model model) {
model.addAttribute("shoppingCartItems", new ShoppingCartItems());
return "hoge";
}
}
hoge.jsp
<c:forEach items="${shoppingCartItems}" var="shoppingCartItem">
<%-- do something --%>
</c:forEach>
Abschließend ohne Verwendung von JSTL. Nur die folgenden Variablen können auf das Attribut items im JSTL forEach-Tag festgelegt werden.
Diese Grenze ist ziemlich streng. Da ich mich diesmal mit Listen beschäftige, denke ich, dass ich den Sammlungstyp implementieren werde, aber ich persönlich wollte den Sammlungstyp vermeiden, da es viele unnötige Methoden gibt. Diesmal habe ich den Iterator-Typ unter der Annahme implementiert, dass die Schleife nur einmal gedreht wird.
ShoppingCartItems.java
public class ShoppingCartItems implements Iterable<ShoppingCartItem>, Iterator<ShoppingCartItem> {
private List<ShoppingCartItem> items = new ArrayList<>();
//Kürzung
private int cursor = 0;
@Override
public boolean hasNext() {
if (cursor < items.size()) {
return true;
}
return false;
}
@Override
public ShoppingCartItem next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return items.get(cursor++); //Wenn Sie es nicht erhöhen, wird es eine Endlosschleife ☆ 彡
}
}
Sie können jetzt eine Instanz der ShoppingCartItems-Klasse im items-Attribut des JSTL forEach-Tags angeben.
Sie können es verwenden, indem Sie die Feldstrommethode für Elemente als Delegierungsmethode für diese ShoppingCartItems definieren. Wenn Sie andere Methoden benötigen, können Sie in dieser Klasse eine Delegierungsmethode definieren, die sofort verwendet werden kann. Es wird jedoch nicht empfohlen, Methoden zu definieren, die unnötige Vorgänge in Ihrer Geschäftslogik ausführen.
ShoppingCartItems.java
public Stream<ShoppingCartItem> stream() {
return items.stream();
}
Erstens besteht der Zweck des Erstellens einer Klasse für die Behandlung von Sammlungen darin, Manipulationen an der Sammlung zu verhindern und den Kohäsionsgrad zu erhöhen. Wenn Sie zu viele Methoden definieren, erfüllt dies nicht Ihren Zweck. Stellen Sie vor dem Definieren einer Methode sicher, dass Sie sie wirklich benötigen.
Ich denke, es ist üblich, Operationen auf Mengen, insbesondere Operationen im Zusammenhang mit Geschäftslogik, in die Service-Klasse zu schreiben. In Zukunft möchte ich in Betracht ziehen, eine Klasse mit einer Menge als Feld zu definieren, um die Geschäftslogik für die Menge an einem Ort zu beschränken.
Recommended Posts