One, the concept:
The strategy pattern defines a series of algorithms, encapsulates each algorithm, and makes them interchangeable, allowing the algorithm to change independently of the client using it.
Second, use the scene
1. When there are multiple handling methods for the same type of problem, only the specific behaviors are different;
2. When multiple operations of the same type need to be safely encapsulated;
3. When there are multiple subclasses of the same abstract class, and you need to use if -else or switch-case to select concrete subclasses.
3. Class diagram
Context role: holds a reference to a Strategy.
Abstract Strategy (Strategy) role: This is an abstract role, usually implemented by an interface or abstract class. This role gives all the interfaces required by concrete policy classes.
ConcreteStrategy Role: Wraps related algorithms or behaviors.
Fourth, the code example
protocol CardInterface { var money: Float{get set} var discountShopping: Float{get} var discountFood: Float{get} var discountRecreation: Float{get} func shopping(standardCost: Float) -> Bool func food(standardCost: Float) -> Bool func recreation(standardCost: Float) -> Bool } class BaseCard: CardInterface { var money: Float var discountShopping: Float var discountFood: Float var discountRecreation: Float init(money: Float, dShopping: Float, dFood: Float, dRecreation: Float) { self.money = money discountShopping = dShopping discountFood = dFood discountRecreation = dRecreation } func shopping(standardCost: Float) -> Bool { if money >= standardCost * discountShopping { money -= standardCost * discountShopping print("success: price(\(standardCost)), cost (\(standardCost * discountShopping)) in fact,left (\(money)),type shopping") return true } print("Lack of balance") return false } func food(standardCost: Float) -> Bool { if money >= standardCost * discountFood { money -= standardCost * discountFood print("success: price(\(standardCost)), cost (\(standardCost * discountFood)) in fact,left (\(money)),type food") return true } print("Lack of balance") return false } func recreation(standardCost: Float) -> Bool { if money >= standardCost * discountRecreation { money -= standardCost * discountRecreation print("success: price(\(standardCost)), cost (\(standardCost * discountRecreation)) in fact,left (\(money)),type recreation") return true } print("Lack of balance") return false } } class NomalCard: BaseCard { init(money: Float) { super.init(money: money, dShopping: 0.88, dFood: 0.9, dRecreation: 0.8) } } class VipCard: BaseCard { init(money: Float) { super.init(money: money, dShopping: 0.8, dFood: 0.8, dRecreation: 0.7) } } class SuperVipCard: BaseCard { init(money: Float) { super.init(money: money, dShopping: 0.7, dFood: 0.75, dRecreation: 0.5) } }
enum CardType: String { Case Nomal case VIP case SuperVIP } class Customer { var card: CardInterface? var cardType: CardType init(cType: CardType) { cardType = cType addCard() } fileprivate func addCard() { switch cardType { Case .Normal: card = NomalCard(money: 100) case .VIP: card = VipCard(money: 100) case .SuperVIP: card = SuperVipCard(money: 100) default: break } } }
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let xiaoMing = Customer(cType: .SuperVIP) var rel = xiaoMing.card?.recreation(standardCost: 88) print(rel ?? false) rel = xiaoMing.card?.recreation(standardCost: 100) print(rel ?? false) rel = xiaoMing.card?.recreation(standardCost: 100) print(rel ?? false) } }