Riepilogo - Elaboratore di pagamenti
Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 46 di 107.
Sfida
FacileCostruiamo un sistema completo di elaborazione dei pagamenti che riunisce tutti i concetti di polimorfismo di questo capitolo. Creerai diversi metodi di pagamento che funzionano tramite un'interfaccia unificata, un processore che accetta qualsiasi metodo di pagamento tramite l'iniezione delle dipendenze ed elaborerai più pagamenti attraverso una raccolta polimorfica.
Organizzerai il codice in quattro file:
payment.go: Definisci un'interfacciaPaymentMethodche richiede un metodoProcess(amount float64) string. Questo è il contratto che tutti i tipi di pagamento devono rispettare.methods.go: Crea tre tipi di pagamento, ciascuno dei quali implementa l'interfacciaPaymentMethod:CreditCardcon i campiCardNumber(string) eHolderName(string). Il suo metodoProcessrestituisceCredit Card [last 4 digits of CardNumber] charged $[amount] to [HolderName]PayPalcon un campoEmail. Il suo metodoProcessrestituiscePayPal payment of $[amount] from [Email]BankTransfercon i campiBankNameeAccountNumber. Il suo metodoProcessrestituisceBank transfer of $[amount] via [BankName] (***[last 3 digits of AccountNumber])
processor.go: Crea una structPaymentProcessorche contiene unPaymentMethod(dipendenza iniettata). Includi un costruttoreNewPaymentProcessorche accetta unPaymentMethod. Aggiungi un metodoExecutePayment(amount float64) stringche delega al metodo di pagamento iniettato. Crea anche una funzioneProcessAll(payments []PaymentMethod, amount float64) []stringche elabora lo stesso importo tramite ciascun metodo di pagamento nella slice e restituisce tutti i risultati.main.go: Leggi i dettagli dei pagamenti dall'input, crea tutti e tre i tipi di pagamento e mostra sia l'iniezione delle dipendenze sia le raccolte polimorfiche. Per prima cosa, usaNewPaymentProcessorcon la carta di credito ed esegui un pagamento. Poi raccogli tutti e tre i metodi di pagamento in una slice e usaProcessAllper elaborarli tutti con un secondo importo. Stampa ogni risultato su una riga separata.
Verranno forniti i seguenti input:
- Riga 1: Numero della carta di credito (ad es.,
4532015112830366) - Riga 2: Nome del titolare della carta
- Riga 3: Email PayPal
- Riga 4: Nome della banca
- Riga 5: Numero del conto (ad es.,
987654321) - Riga 6: Primo importo del pagamento (per il processore singolo)
- Riga 7: Secondo importo del pagamento (per l'elaborazione in batch)
Formatta gli importi con due cifre decimali. Ad esempio, dati 4532015112830366, John Smith, john@email.com, Chase, 987654321, 99.99 e 50, l'output dovrebbe essere:
Credit Card 0366 charged $99.99 to John Smith
Credit Card 0366 charged $50.00 to John Smith
PayPal payment of $50.00 from john@email.com
Bank transfer of $50.00 via Chase (***321)La prima riga mostra il pagamento singolo tramite il processore con dipendenza iniettata. Le tre righe rimanenti mostrano l'elaborazione in batch tramite la raccolta polimorfica: la stessa funzione ProcessAll gestisce uniformemente tutti i tipi di pagamento, mostrando come le interfacce consentano di creare sistemi di pagamento flessibili ed estensibili.
Provalo tu
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Leggi l'input
cardNumber, _ := reader.ReadString('\n')
cardNumber = strings.TrimSpace(cardNumber)
holderName, _ := reader.ReadString('\n')
holderName = strings.TrimSpace(holderName)
email, _ := reader.ReadString('\n')
email = strings.TrimSpace(email)
bankName, _ := reader.ReadString('\n')
bankName = strings.TrimSpace(bankName)
accountNumber, _ := reader.ReadString('\n')
accountNumber = strings.TrimSpace(accountNumber)
amount1Str, _ := reader.ReadString('\n')
amount1Str = strings.TrimSpace(amount1Str)
amount1, _ := strconv.ParseFloat(amount1Str, 64)
amount2Str, _ := reader.ReadString('\n')
amount2Str = strings.TrimSpace(amount2Str)
amount2, _ := strconv.ParseFloat(amount2Str, 64)
// TODO: Crea i tre tipi di pagamento (CreditCard, PayPal, BankTransfer)
// TODO: Crea un PaymentProcessor con la carta di credito usando NewPaymentProcessor
// ed esegui un pagamento con amount1, poi stampa il risultato
// TODO: Crea uno slice di PaymentMethod contenente tutti e tre i tipi di pagamento
// TODO: Usa ProcessAll per elaborare tutti i pagamenti con amount2
// e stampa ogni risultato su una riga separata
}
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti di OOP in Go
File esterniWorkspace e moduli GoPacchetti e importazioniNomi esportati e non esportatiIntroduzione all’OOP in GoGli struct come classiDefinire metodi sugli structReceiver con puntatore vs receiver con valoreInizializzazione degli structFunzioni costruttriciRiepilogo - Calcolatrice semplice4Interfacce
Introduzione alle interfacceImplementazione implicitaL’interfaccia come contrattoInterfaccia vuota (any)Asserzione di tipoSwitch sul tipoComposizione di interfacceInterfacce Stringer ed ErrorRipasso - Calcolatore di forme7Incapsulamento
Campi esportati e non esportatiIncapsulamento a livello di packageMetodi Getter e SetterNascondimento delle informazioni in GoRiepilogo - Registri degli studenti10Tipi generici (Go 1.18+)
Introduzione ai tipi genericiParametri di tipoVincoli di tipoStruct genericheSoluzione alternativa per i metodi genericiRiepilogo - Collezione generica13Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneModello SingletonModello FactoryModello Abstract FactoryModello ObserverModello Strategy2Approfondimento su tipi e struct
Tipi di base e compostiDefinizioni di tipi personalizzatiTag delle structStruct anonimeStruct annidateValori zero e predefinitiRipasso - Rubrica5Composizione invece dell'ereditarietà
Perché Go non ha l'ereditarietàFondamenti dell'embedding delle structPromozione dei metodiEmbedding di più structEmbedding e aggregazione a confrontoMascheramento dei metodi embeddedRiepilogo: gerarchia dei dipendenti8Gestione degli errori e OOP
L'interfaccia errorTipi di errore personalizzatiWrapping degli errori (fmt.Errorf)Errori sentinellaerrors.Is() ed errors.As()Panic, Defer e RecoverRiepilogo - Parser di file11Libreria standard e OOP
io.Reader e io.Writersort.InterfaceInterfaccia fmt.Stringerencoding/json con le structInterfaccia http.HandlerRipasso - modelli REST API14Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositeMiddleware come Decorator3Puntatori e memoria
Concetti base dei puntatori in GoPuntatori a structPassaggio per valore vs per riferimentoLa funzione new()Garbage collection in GoRiepilogo - Costruttore di liste concatenate6Polimorfismo in Go
Polimorfismo tramite interfacceDuck typing in GoRegole di soddisfacimento delle interfacceCollezioni polimorficheIniezione delle dipendenzeRiepilogo - Elaboratore di pagamenti9Concorrenza e OOP
Basi delle goroutineCanali e comunicazioneCanali bufferizzati vs non bufferizzatiIstruzione selectsync.Mutex e sync.RWMutexsync.WaitGroupProgettazione di struct thread-safeRiepilogo: worker poolEsercitati da solo: Compilatore Go online