设计模式之策略模式

2017-03-24  本文已影响9人  JohnnyB0Y

策略模式

是什么?

策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法。

怎么做?

定义了算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

遵守原则?

第一步,区分客户和一族算法:

以上面税收的例子,人就是客户。人可以是美国人、中国人。一族算法就是交个人所得税,有美国的算税方法,有中国特色的算税方法。

第二步,抽象代码:
// 客户的抽象
class Human: NSObject {
// 人类共同的属性和行为
}

class American: Human {
// 美国人特殊的属性和行为
}

class Chinese: Human {
// 中国人特殊的属性和行为
}

// 一族算法的抽象
protocol PayTaxBehavior {
    // 交税的协议
    func payingTaxes()
}

class ChinaTax: NSObject, PayTaxBehavior {
    // 中国税收计算
    func payingTaxes() {
        print("中国税收计算!")
    }
}

class AmericanTax: NSObject, PayTaxBehavior {
    // 美国税收计算
    func payingTaxes() {
        print("美国税收计算!")
    }
}

第三步,组合调用:

为什么示例代码是鸭子?因为我已经写好了,所以直接拷贝好了。

1.0 一族算法的协议

protocol FlyBehavior {
    func fly()
}
protocol QuackBehavior {
    func quack()
}

2.0 实现协议的算法类

class FlyWithWings: NSObject, FlyBehavior {
    func fly() {
        print("I am fly with wings.")
    }
}
class FlyNoWay: NSObject, FlyBehavior {
    func fly() {
        print("I am fly no way.")
    }
}
class Quack: NSObject, QuackBehavior {
    func quack() {
        print("quack quack quack!")
    }
}
class Squeak: NSObject, QuackBehavior {
    func quack() {
        print("squeak squeak squeak!")
    }
}
class MuteQuack: NSObject, QuackBehavior {
    func quack() {
        print("Mute quack.")
    }
}

** 3.0 用户的抽象类**

class Duck: NSObject {
    // 遵守协议的一族算法对象,私有是为了不让子类直接访问。
    private var quackBehavior: QuackBehavior?
    private var flyBehavior: FlyBehavior?

    // 提供接口,让算法可互换代替
    public func setQuackBehavior( quackBehavior : QuackBehavior )
    {
        self.quackBehavior = quackBehavior
    }
    public func setFlyBehavior( flyBehavior : FlyBehavior )
    {
        self.flyBehavior = flyBehavior
    }

    // 可能某些鸭子没有的行为,提供接口调用封装好的算法。
    public func performFly()
    {
        flyBehavior?.fly()
    }
    public func performQuack()
    {
        quackBehavior?.quack()
    }

    // 鸭子共有的行为,可以直接继承。不同于父类的可以重写。
    public func swim()
    {
        print("I am swimming!!!")
    }
    public func name()
    {
        print("I am duck.")
    }
}

4.0 具体的用户

class DuckA: Duck {
    override init() {
        super.init()
        // 子类有自己的默认行为。
        self.setFlyBehavior(flyBehavior: FlyWithWings())
        self.setQuackBehavior(quackBehavior: Quack())
    }
    public override func name() {
        print("I am duck A.")
    }
}
class DuckB: Duck {
    override init() {
        super.init()
        // B 也有自己的默认行为
        self.setFlyBehavior(flyBehavior: FlyWithWings())
        self.setQuackBehavior(quackBehavior: Squeak())
    }
    public override func name() {
        print("I am duck B.")
    }
}
class DuckC: Duck {
    override init() {
        super.init()
        // C 也有自己的默认行为
        self.setFlyBehavior(flyBehavior: FlyNoWay())
        self.setQuackBehavior(quackBehavior: MuteQuack())
    }
    public override func name() {
        print("I am duck C.")
    }
}

5.0 测试代码

let duck = DuckC()

// 我们有不一样的名字
duck.name()
// 但我们都会游泳
duck.swim()

// 调用默认行为
duck.performFly()
duck.performQuack()

// 改变行为
duck.setQuackBehavior(quackBehavior: Squeak())
duck.setFlyBehavior(flyBehavior: FlyWithWings())

// 调用改变后的行为
duck.performFly()
duck.performQuack()

策略模式的优点

缺点

参考资料

维基百科-策略模式

上一篇下一篇

猜你喜欢

热点阅读