Parfois, j'ai créé un écran pour afficher deux types de données ensemble dans une table. À cette époque, j'ai pu l'implémenter proprement en utilisant le polymorphisme en utilisant une interface au lieu du branchement conditionnel. Je voudrais vous présenter les avantages du code actuel.
L'ensemble du code peut être trouvé sur GitHub. Veuillez me pardonner bien qu'il puisse y avoir une pénurie parce que je vais l'expliquer brièvement.
Je vais vous donner un programme extrêmement sale, mais j'ai implémenté l'exemple en utilisant le branchement conditionnel comme suit.
monomorphism/PurchaseController.java
@Controller
@RequestMapping("monomorphism/purchase")
public class PurchaseController {
//La description de DI de service est omise.
@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}Clé de format et carte de contrat
Map<String, Contract> contractMap = memberContracts.stream().collect(Collectors.toMap(c -> "c-" + c.id, c -> c));
modelAndView.addObject("memberContracts", contractMap);
// p-{id}Formater la clé et la carte d'achat
Map<String, Purchase> purchaseMap = memberPurchases.stream().collect(Collectors.toMap(p -> "p-" + p.id, p -> p));
modelAndView.addObject("memberPurchases", purchaseMap);
//Générer l'identifiant et la date d'achat Cartographier et trier par date d'achat
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>Date d'achat</th>
<th>Nom du produit acheté</th>
<th>Prix unitaire</th>
<th>Nombre d'achats</th>
<th>total</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}Cercle/${contract.service.unitMonths}mois|"></td>
<td th:text="|${contract.months}mois|"></td>
<td th:text="|${contract.service.priceByUnitMonth / contract.service.unitMonths * contract.months - contract.service.yearlyDiscount}Cercle|"></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}Cercle|"></td>
<td th:text="|${purchase.amount}Pièces|"></td>
<td th:text="|${purchase.commodity.unitPrice * purchase.amount}Cercle|"></td>
</th:block>
</tr>
</tbody>
</table>
Le contrôleur et la vue sont complexes, même si l'historique des contrats et l'historique des achats ne sont affichés que dans une liste.
Dans l'exemple utilisant le polymorphisme, il a été implémenté comme suit.
polymorphism.PurchaseService.java
@Service
public class PurchaseService {
//La description de DI du référentiel est omise
public List<PurchaseHistory> getMemberPurchaseHistory(Integer memberId) {
//Acquérir des données d'achat de produit et les convertir en une classe d'historique d'achat de produit qui implémente le type d'historique d'achat
List<Purchase> purchases = purchaseRepository.findByMemberId(memberId);
Stream<CommodityPurchaseHistory> commodityPurchaseHistoryStream = purchases.stream().map(CommodityPurchaseHistory::new);
//Acquérir des données de contrat de service et les convertir en une classe d'historique d'achat de service qui implémente le type d'historique d'achat
List<Contract> contracts = contractRepository.findByMemberId(memberId);
Stream<ServicePurchaseHistory> contractHistoryStream = contracts.stream().map(ServicePurchaseHistory::new);
//Combinez des listes de types d'historique d'achat et triez par date d'achat
return Stream.concat(commodityPurchaseHistoryStream, contractHistoryStream)
.sorted(Comparator.comparing(PurchaseHistory::purchasedDate))
.collect(Collectors.toList());
}
}
polymorphism.PolyPurchaseController.java
@Controller
@RequestMapping("polymorphism/purchase")
public class PolyPurchaseController {
//La description de DI de service est omise.
@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;
}
}
La description de la vue est très rafraîchissante car elle n'appelle que la méthode de type historique des achats.
polymorphism/list.html
<table class="uk-table">
<thead>
<th>Date d'achat</th>
<th>Nom du produit acheté</th>
<th>Prix unitaire</th>
<th>Nombre d'achats</th>
<th>total</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>
Que vous utilisiez le polymorphisme ou non, il est préférable de conserver les calculs et les conditions dans un programme côté serveur.
Je pense que la plupart des concepteurs qui collaborent avec nous n'ont aucune connaissance du moteur de template de Java, donc je pense qu'il est préférable de garder le fichier Html simple. Si vous concevez et programmez en tenant compte du type de technologie dont disposent vos collègues et du meilleur type de répartition des rôles, vous pouvez aborder le succès de toute l'équipe de développement.
En plus de cela, si vous utilisez le polymorphisme, vous pouvez écrire un programme avec une bonne visibilité en réduisant les instructions if du programme côté serveur.
Recommended Posts