Swift Example
/// Strategy Design Pattern
///
/// Intent: Lets you define a family of algorithms, put each of them into a
/// separate class, and make their objects interchangeable.
import XCTest
/// The Context defines the interface of interest to clients.
class Context {
/// The Context maintains a reference to one of the Strategy objects. The
/// Context does not know the concrete class of a strategy. It should work
/// with all strategies via the Strategy interface.
private var strategy: Strategy
/// Usually, the Context accepts a strategy through the constructor, but
/// also provides a setter to change it at runtime.
init(strategy: Strategy) {
self.strategy = strategy
}
/// Usually, the Context allows replacing a Strategy object at runtime.
func update(strategy: Strategy) {
self.strategy = strategy
}
/// The Context delegates some work to the Strategy object instead of
/// implementing multiple versions of the algorithm on its own.
func doSomeBusinessLogic() {
print("Context: Sorting data using the strategy (not sure how it'll do it)\n")
let result = strategy.doAlgorithm(["a", "b", "c", "d", "e"])
print(result.joined(separator: ","))
}
}
/// The Strategy interface declares operations common to all supported versions
/// of some algorithm.
///
/// The Context uses this interface to call the algorithm defined by Concrete
/// Strategies.
protocol Strategy {
func doAlgorithm<T: Comparable>(_ data: [T]) -> [T]
}
/// Concrete Strategies implement the algorithm while following the base
/// Strategy interface. The interface makes them interchangeable in the Context.
class ConcreteStrategyA: Strategy {
func doAlgorithm<T: Comparable>(_ data: [T]) -> [T] {
return data.sorted()
}
}
class ConcreteStrategyB: Strategy {
func doAlgorithm<T: Comparable>(_ data: [T]) -> [T] {
return data.sorted(by: >)
}
}
/// Let's see how it all works together.
class StrategyConceptual: XCTestCase {
func test() {
/// The client code picks a concrete strategy and passes it to the
/// context. The client should be aware of the differences between
/// strategies in order to make the right choice.
let context = Context(strategy: ConcreteStrategyA())
print("Client: Strategy is set to normal sorting.\n")
context.doSomeBusinessLogic()
print("\nClient: Strategy is set to reverse sorting.\n")
context.update(strategy: ConcreteStrategyB())
context.doSomeBusinessLogic()
}
}
Client: Strategy is set to normal sorting.
Context: Sorting data using the strategy (not sure how it'll do it)
a,b,c,d,e
Client: Strategy is set to reverse sorting.
Context: Sorting data using the strategy (not sure how it'll do it)
e,d,c,b,a