Musterdekorateur

Das Decorator-Muster bezieht sich auf strukturelle Designmuster.

Der Dekorator wird als Alternative zur Vererbung verwendet, um die Funktionalität von Klassen zu erweitern.
Je nach Produkttyp besteht die Aufgabe, die Funktionalität der Anwendung zu erweitern. Der Kunde benötigt drei Arten von Produkten – Einfach, professionell, ultimativ.
Basic– zählt die Anzahl der Zeichen, Professional – Funktionen Basic + druckt Text in Großbuchstaben, Ultimate – Basic + Professional + druckt Text mit der Aufschrift ULTIMATE.
Wir implementieren es mithilfe der Vererbung:

protocol Feature {
	func textOperation(text: String)
}

class BasicVersionFeature: Feature {
	func textOperation(text: String) {
		print("\(text.count)")
	}
}

class ProfessionalVersionFeature: BasicVersionFeature {
	override func textOperation(text: String) {
		super.textOperation(text: text)
		print("\(text.uppercased())")
	}
}

class UltimateVersionFeature: ProfessionalVersionFeature {
	override func textOperation(text: String) {
		super.textOperation(text: text)
		print("ULTIMATE: \(text)")
	}
}

let textToFormat = "Hello Decorator"

let basicProduct = BasicVersionFeature()
basicProduct.textOperation(text: textToFormat)

let professionalProduct = ProfessionalVersionFeature()
professionalProduct.textOperation(text: textToFormat)

let ultimateProduct = UltimateVersionFeature()
ultimateProduct.textOperation(text: textToFormat)

Jetzt besteht die Anforderung, das Produkt „Ultimate Light“ umzusetzen – Basic + Ultimate, jedoch ohne die Funktionen der Professional-Version. Das erste OH! passiert, weil… Sie müssen für eine so einfache Aufgabe eine separate Klasse erstellen und den Code duplizieren.
Lassen Sie uns die Implementierung mithilfe der Vererbung fortsetzen:

protocol Feature {
	func textOperation(text: String)
}

class BasicVersionFeature: Feature {
	func textOperation(text: String) {
		print("\(text.count)")
	}
}

class ProfessionalVersionFeature: BasicVersionFeature {
	override func textOperation(text: String) {
		super.textOperation(text: text)
		print("\(text.uppercased())")
	}
}

class UltimateVersionFeature: ProfessionalVersionFeature {
	override func textOperation(text: String) {
		super.textOperation(text: text)
		print("ULTIMATE: \(text)")
	}
}

class UltimateLightVersionFeature: BasicVersionFeature {
	override func textOperation(text: String) {
		super.textOperation(text: text)
		print("ULTIMATE: \(text)")	
	}
}

let textToFormat = "Hello Decorator"

let basicProduct = BasicVersionFeature()
basicProduct.textOperation(text: textToFormat)

let professionalProduct = ProfessionalVersionFeature()
professionalProduct.textOperation(text: textToFormat)

let ultimateProduct = UltimateVersionFeature()
ultimateProduct.textOperation(text: textToFormat)

let ultimateLightProduct = UltimateLightVersionFeature()
ultimateLightProduct.textOperation(text: textToFormat)

Das Beispiel kann zur Verdeutlichung weiterentwickelt werden, aber schon jetzt ist die Komplexität der Unterstützung eines Systems auf Basis einer Vererbungsbasis sichtbar – umständlich und mangelnde Flexibilität.
Ein Dekorator ist eine Reihe von Protokollen, die die Funktionalität beschreiben, eine abstrakte Klasse, die einen Verweis auf eine untergeordnete konkrete Instanz der Dekoratorklasse enthält, die die Funktionalität erweitert.
Schreiben wir das obige Beispiel mit dem Muster um:

protocol Feature {
	func textOperation(text: String)
}

class FeatureDecorator: Feature {
	private var feature: Feature?
	
	init(feature: Feature? = nil) {
		self.feature = feature
	}
	
	func textOperation(text: String) {
		feature?.textOperation(text: text)
	}
}

class BasicVersionFeature: FeatureDecorator {
	override func textOperation(text: String) {
		super.textOperation(text: text)
		print("\(text.count)")
	}
}

class ProfessionalVersionFeature: FeatureDecorator {
	override func textOperation(text: String) {
		super.textOperation(text: text)
		print("\(text.uppercased())")
	}
}

class UltimateVersionFeature: FeatureDecorator {
	override func textOperation(text: String) {
		super.textOperation(text: text)
		print("ULTIMATE: \(text)")
	}
}

let textToFormat = "Hello Decorator"

let basicProduct = BasicVersionFeature(feature: UltimateVersionFeature())
basicProduct.textOperation(text: textToFormat)

let professionalProduct = ProfessionalVersionFeature(feature: UltimateVersionFeature())
professionalProduct.textOperation(text: textToFormat)

let ultimateProduct = BasicVersionFeature(feature: UltimateVersionFeature(feature: ProfessionalVersionFeature()))
ultimateProduct.textOperation(text: textToFormat)

let ultimateLightProduct = BasicVersionFeature(feature: UltimateVersionFeature())
ultimateLightProduct.textOperation(text: textToFormat)

Jetzt können wir Variationen jeder Art von Produkt erstellen – Es reicht aus, die kombinierten Typen beim Anwendungsstart zu initialisieren. Das folgende Beispiel zeigt die Erstellung der Ultimate + Professional-Version:

ultimateProfessionalProduct.textOperation(text: textToFormat)

Quellen

https://refactoring.guru/ru/design-patterns/decorator

Quellcode

https://gitlab.com/demensdeum/patterns

Leave a Comment

Your email address will not be published. Required fields are marked *