Wzorzec fabryki
Część sekcji Programowanie obiektowe ścieżki Swift w Coddy. Lekcja 43 z 57.
Wzorzec fabryki umieszcza tworzenie obiektów w jednym miejscu. Wywołujący proszą o to, czego potrzebują, często podając nazwę lub typ, i otrzymują gotowy obiekt, nie wiedząc, jaki konkretny typ został utworzony:
protocol Shape { func area() -> Double }
struct Square: Shape { let side: Double; func area() -> Double { side * side } }
struct Circle: Shape { let r: Double; func area() -> Double { 3 * r * r } }
enum ShapeFactory {
static func make(_ kind: String, size: Double) -> (any Shape)? {
switch kind {
case "square": return Square(side: size)
case "circle": return Circle(r: size)
default: return nil
}
}
}
print(ShapeFactory.make("square", size: 3)!.area())
print(ShapeFactory.make("hexagon", size: 3) == nil)Wynik:
9.0
trueWywołujący zależy tylko od protokołu. Dodanie nowego kształtu oznacza zmianę fabryki, a nie każdego miejsca, w którym tworzone są kształty:
protocol Notifier { func send(_ m: String) -> String }
struct Email: Notifier { func send(_ m: String) -> String { "email: \(m)" } }
struct SMS: Notifier { func send(_ m: String) -> String { "sms: \(m)" } }
func makeNotifier(for user: String) -> any Notifier {
user.hasSuffix("@mail.com") ? Email() : SMS()
}
print(makeNotifier(for: "ada@mail.com").send("hi"))
print(makeNotifier(for: "555-0100").send("hi"))Wynik:
email: hi
sms: hiStatyczne metody fabrykujące w samym typie są lżejszą formą tego wzorca. Nadają nazwy typowym sposobom tworzenia wartości:
struct Color {
let r: Int, g: Int, b: Int
static func gray(_ v: Int) -> Color { Color(r: v, g: v, b: v) }
static let white = Color(r: 255, g: 255, b: 255)
}
print(Color.gray(100).g)
print(Color.white.b)Wynik:
100
255Enum bez przypadków, taki jak ShapeFactory, to popularny sposób grupowania funkcji fabrykujących: nie można utworzyć jego instancji, więc służy wyłącznie jako przestrzeń nazw.
enum ShapeFactory { // brak przypadków: nie można utworzyć instancji
static func make(_ kind: String, size: Double) -> (any Shape)? { ... }
}Wyzwanie
ŁatwyNapisz fabrykę planów cenowych. Protokół Plan ma name i price(forUsers:) -> Int. Zaimplementuj Free (0, ale tylko dla maksymalnie 3 użytkowników: powyżej tej liczby cena wynosi -1, co oznacza, że plan jest niedozwolony), Team (10 za użytkownika) oraz Enterprise (stała opłata 500 plus 5 za każdego użytkownika powyżej 100). Uzupełnij PlanFactory.make(_:), która zwraca plan dla free, team lub enterprise, a w pozostałych przypadkach nil.
Dostarczony kod odczytuje wiersze plan,users i wypisuje team for 12 users: 120, free does not allow 5 users lub unknown plan: gold.
Twój kod umieść w plikach Plan.swift, Free.swift, Team.swift, Enterprise.swift i PlanFactory.swift. Plik main.swift zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
// Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
let p = line.split(separator: ",").map(String.init)
let users = Int(p[1])!
guard let plan = PlanFactory.make(p[0]) else {
print("unknown plan: \(p[0])")
continue
}
let price = plan.price(forUsers: users)
print(price < 0 ? "\(plan.name) does not allow \(users) users" : "\(plan.name) for \(users) users: \(price)")
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Klasy i obiekty
Praca z plikamiDefiniowanie klasMetody i selfInicjalizatoryKlasy są referencjamiPowtórzenie — karta biblioteczna4Hermetyzacja
Kontrola dostępuTylko do odczytu z zewnątrzOchrona stanuInicjalizatory, które mogą zawieśćPodsumowanie — konto bankowe7Polimorfizm i typy generyczne
PolimorfizmRzutowanie typówFunkcje generyczneTypy generycznePodsumowanie – kalkulator kształtów2Struktury i typy wartościowe
StrukturySemantyka wartościMetody modyfikująceStruktura czy klasaPodsumowanie – element inwentarza5Dziedziczenie
PodklasyPrzesłanianie metodInicjalizatory i superfinal i hierarchiePodsumowanie — hierarchia pracowników8Standardowe protokoły
CustomStringConvertibleEquatableComparableHashablePodsumowanie — własne sortowanie11Projekt: Zarządzanie biblioteką
Książki i czytelnicyWypożyczanie książekPoćwicz samodzielnie: Edytor online Swift