Manchmal habe ich einen Bildschirm erstellt, auf dem zwei Datentypen zusammen in einer Tabelle angezeigt werden. Zu dieser Zeit war ich in der Lage, es sauber zu implementieren, indem ich Polymorphismus unter Verwendung einer Schnittstelle anstelle einer bedingten Verzweigung verwendete. Ich möchte vorstellen, welche Vorteile der eigentliche Code bietet.
Das Gesamtbild des Codes wird auf GitHub hochgeladen. Bitte verzeihen Sie mir, obwohl es möglicherweise einen Mangel gibt, da ich ihn kurz erläutern werde.
Ich werde Ihnen ein extrem schmutziges Programm geben, aber ich habe das Beispiel unter Verwendung der bedingten Verzweigung wie folgt implementiert.
monomorphism/PurchaseController.java
@Controller
@RequestMapping("monomorphism/purchase")
public class PurchaseController {
//Die Beschreibung zu DI of Service wird weggelassen.
@GetMapping("list/{memberId}")
public ModelAndView listByBadDto(@PathVariable Integer memberId) {
List<Contract> memberContracts = purchaseHistoryQueryService.getMemberContracts(memberId);
List<Purchase> memberPurchases = purchaseHistoryQueryService.getMemberPurchases(memberId);
ModelAndView modelAndView = new ModelAndView("monomorphism/complex");
// c-{id}Formatschlüssel und Vertragskarte
Map<String, Contract> contractMap = memberContracts.stream().collect(Collectors.toMap(c -> "c-" + c.id, c -> c));
modelAndView.addObject("memberContracts", contractMap);
// p-{id}Formatschlüssel und Kaufkarte
Map<String, Purchase> purchaseMap = memberPurchases.stream().collect(Collectors.toMap(p -> "p-" + p.id, p -> p));
modelAndView.addObject("memberPurchases", purchaseMap);
//ID und Kaufdatum generieren Karte und nach Kaufdatum sortieren
Map<String, LocalDate> contractDateMap = contractMap.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().beginDate));
Map<String, LocalDate> purchaseDateMap = purchaseMap.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().purchasedDate));
Map<String, LocalDate> idMap = new HashMap<>();
idMap.putAll(contractDateMap);
idMap.putAll(purchaseDateMap);
List<String> ids = idMap.entrySet().stream()
.sorted(Comparator.comparing(Map.Entry::getValue))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
modelAndView.addObject("ids", ids);
return modelAndView;
}
}
monomorohism/complex.html
<table class="uk-table">
<thead>
<tr>
<th>Kaufdatum</th>
<th>Gekaufter Produktname</th>
<th>Stückpreis</th>
<th>Anzahl der Einkäufe</th>
<th>Zwischensumme</th>
</tr>
</thead>
<tbody>
<tr th:each="id: ${ids}">
<th:block th:if="${id.startsWith('c-')}" th:with="contract = ${memberContracts.get(id)}">
<td th:text="${contract.beginDate}"></td>
<td th:text="${contract.service.name}"></td>
<td th:text="|${contract.service.priceByUnitMonth}Kreis/${contract.service.unitMonths}Monate|"></td>
<td th:text="|${contract.months}Monate|"></td>
<td th:text="|${contract.service.priceByUnitMonth / contract.service.unitMonths * contract.months - contract.service.yearlyDiscount}Kreis|"></td>
</th:block>
<th:block th:if="${id.startsWith('p-')}" th:with="purchase = ${memberPurchases.get(id)}">
<td th:text="${purchase.purchasedDate}"></td>
<td th:text="${purchase.commodity.name}"></td>
<td th:text="|${purchase.commodity.unitPrice}Kreis|"></td>
<td th:text="|${purchase.amount}Stücke|"></td>
<td th:text="|${purchase.commodity.unitPrice * purchase.amount}Kreis|"></td>
</th:block>
</tr>
</tbody>
</table>
Der Controller und die Ansicht sind kompliziert, obwohl der Vertragsverlauf und der Kaufverlauf nur in einer Liste angezeigt werden.
In dem Beispiel unter Verwendung von Polymorphismus wurde es wie folgt implementiert.
polymorphism.PurchaseService.java
@Service
public class PurchaseService {
//Die Beschreibung zu DI des Repositorys wird weggelassen
public List<PurchaseHistory> getMemberPurchaseHistory(Integer memberId) {
//Erfassen Sie Produktkaufdaten und konvertieren Sie sie in eine Produktkaufverlaufsklasse, die den Kaufverlaufstyp implementiert
List<Purchase> purchases = purchaseRepository.findByMemberId(memberId);
Stream<CommodityPurchaseHistory> commodityPurchaseHistoryStream = purchases.stream().map(CommodityPurchaseHistory::new);
//Erfassen Sie Servicevertragsdaten und konvertieren Sie sie in eine Servicekaufverlaufsklasse, die den Kaufverlaufstyp implementiert
List<Contract> contracts = contractRepository.findByMemberId(memberId);
Stream<ServicePurchaseHistory> contractHistoryStream = contracts.stream().map(ServicePurchaseHistory::new);
//Kombinieren Sie Listen mit Kaufverlaufstypen und sortieren Sie nach Kaufdatum
return Stream.concat(commodityPurchaseHistoryStream, contractHistoryStream)
.sorted(Comparator.comparing(PurchaseHistory::purchasedDate))
.collect(Collectors.toList());
}
}
polymorphism.PolyPurchaseController.java
@Controller
@RequestMapping("polymorphism/purchase")
public class PolyPurchaseController {
//Die Beschreibung zu DI of Service wird weggelassen.
@GetMapping("list/{memberId}")
public ModelAndView getInterface(@PathVariable("memberId") Integer memberId) {
List<PurchaseHistory> memberPurchaseHistories = purchaseService.getMemberPurchaseHistory(memberId);
ModelAndView modelAndView = new ModelAndView("polymorphism/list");
modelAndView.addObject("memberPurchaseHistories", memberPurchaseHistories);
return modelAndView;
}
}
Die Beschreibung der Ansicht ist sehr erfrischend, da nur die Methode des Kaufverlaufstyps aufgerufen wird.
polymorphism/list.html
<table class="uk-table">
<thead>
<th>Kaufdatum</th>
<th>Gekaufter Produktname</th>
<th>Stückpreis</th>
<th>Anzahl der Einkäufe</th>
<th>Zwischensumme</th>
</thead>
<tbody>
<tr th:each="purchaseHistory : ${memberPurchaseHistories}">
<td th:text="${purchaseHistory.purchasedDate()}"></td>
<td th:text="${purchaseHistory.purchasedCommodityName()}"></td>
<td th:text="${purchaseHistory.unitPrice()}"></td>
<td th:text="${purchaseHistory.amount()}"></td>
<td th:text="${purchaseHistory.subtotal()}"></td>
</tr>
</tbody>
</table>
Unabhängig davon, ob Sie Polymorphismus verwenden oder nicht, ist es besser, Berechnungen und Bedingungen in einem serverseitigen Programm beizubehalten.
Ich denke, dass die meisten Designer, die mit uns zusammenarbeiten, keine Kenntnisse über Java Template Engines haben. Daher denke ich, dass es am besten ist, HTML-Dateien einfach zu halten. Wenn Sie mit dem Bewusstsein entwerfen und programmieren, über welche Technologie Ihre Kollegen verfügen und welche Art von Rollenteilung am besten ist, können Sie sich dem Erfolg des gesamten Entwicklungsteams nähern.
Wenn Sie Polymorphismus verwenden, können Sie außerdem ein Programm mit guter Sichtbarkeit schreiben, indem Sie die if-Anweisungen des serverseitigen Programms reduzieren.
Recommended Posts