[JAVA] Eine Geschichte, die mithilfe von Polymorphismus sauber implementiert werden kann, wenn Sie zwei Datentypen in einer Tabelle ausdrücken möchten

Eine Geschichte, die mithilfe von Polymorphismus sauber implementiert werden kann, wenn Sie zwei Datentypen in einer Tabelle ausdrücken möchten

Überblick

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.

Annahme

Entwicklungsumgebung

Spezifikation

  1. Anzeigen des Produktkaufverlaufs und des Abonnement-Servicevertragsverlaufs bei Amazon
  2. Ich möchte in chronologischer Reihenfolge anzeigen, unabhängig von der Kaufhistorie des Produkts oder der Vertragshistorie des Abonnementdienstes.
  3. Kaufdatum, Produktname, Stückpreis, Anzahl der Einkäufe, Zwischensumme anzeigen
  4. Zeigen Sie bei Abonnementverträgen das Vertragsbeginndatum, den Servicenamen, den Stückpreis, die Vertragsmonate und die Zwischensumme an.
  5. Abonnementverträge erhalten Rabatte, wenn sie jährlich abgeschlossen werden

Bildschirmbild

スクリーンショット 2019-06-24 12.38.30.png

2 Arten von Beispielcode

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.

Beispiel mit bedingter Verzweigung

Ich werde Ihnen ein extrem schmutziges Programm geben, aber ich habe das Beispiel unter Verwendung der bedingten Verzweigung wie folgt implementiert.

  1. Rufen Sie Daten aus Kauf- und Vertragsverlauf ab und speichern Sie sie in einem assoziativen Array
  2. Extrahieren Sie den Schlüssel des assoziativen Arrays und das Kaufdatum / Vertragsdatum und erstellen Sie eine Liste, in der die IDs in aufsteigender Reihenfolge des Datums sortiert sind.
  3. Zeigen Sie die Kauf- und Vertragsgeschichte in der Reihenfolge der ID-Liste auf dem Bildschirm an

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.

Beispiel mit Polymorphismus

In dem Beispiel unter Verwendung von Polymorphismus wurde es wie folgt implementiert.

  1. Konvertieren Sie Kaufdaten und Vertragsdaten aus der Datenbank in eine Kaufverlaufsklasse
  2. Sortieren Sie die Daten des Kaufverlaufstyps in der Reihenfolge des Kaufdatums und zeigen Sie sie auf dem Bildschirm an

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>

schließlich

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

Eine Geschichte, die mithilfe von Polymorphismus sauber implementiert werden kann, wenn Sie zwei Datentypen in einer Tabelle ausdrücken möchten
Ich möchte, dass Sie die Geschichte erzählen, dass der Fehler behoben wurde, als Sie das Ladegerät in die Ecke Ihres Kopfes gestochen haben
[Swift] Wenn Sie wissen möchten, ob die Anzahl der Zeichen in String mit einer bestimmten Anzahl übereinstimmt ...
Eine Sammlung von Mustern, die Sie kennen möchten, um den Code nicht zu komplizieren
Ein Memorandum, wenn Sie die von Jena & SPARQL erfassten Daten für jede Variable anzeigen möchten.
So erstellen Sie ein Schlüsselpaar von ecdsa in einem Format, das von Java gelesen werden kann
So implementieren Sie eine Diashow mit Slick in Rails (einzeln und mehrfach nacheinander)
Wenn Sie irgendwo einen Fehler melden möchten, wenn Sie graphql-spring-boot mit Spring Boot verwenden
So erstellen Sie eine eindeutige Datenkombination in der Schienen-Zwischentabelle
Eine Geschichte, dass eine Person, die ein solides iOS gemacht hat, möglicherweise von der Implementierung von Listener abhängig ist, wenn sie zu Android wechselt