策略模式

1.定义

策略模式:定义了算法簇[cù],分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

2.背景

(本来是打算用自己业务中的某个场景来进行讲解的,很遗憾之前并没有使用过该模式,之后会尝试使用)

Joe上班的公司做了一套相当成功的模拟鸭子游戏;SimUDuck。游戏中会出现各种鸭子,一边游泳戏水,一边呱呱叫。此系统的内部设计使用了标准的OO技术,设计了一个鸭子的超类(Superclass),并让各种鸭子继承此超类。但是为了提高竞争力,主管们确定,此模拟程序需要会飞的鸭子来将竞争者抛在后面。

3.方案

1.Joe首先想到的方法是在Duck类中加上fly()方法,然后所有鸭子都会继承fly()。但是这个会出现所有的鸭子都有了飞的功能(包括“橡皮鸭子”),他体会到了一件事:当涉及“维护”时,为了“复用”目的而使用继承,结局并不完美。

2.Joe之后想到的是,继续采用在Duck中添加fly()方法,可以把橡皮鸭中的fly()方法覆盖掉,可是以后我们加入诱饵鸭,又会如何?诱饵鸭是木头假鸭,不会飞也不会叫。显然这并不是一个好的解决方案,每当有新的鸭子子类出现,他就要被迫检查并可能需要覆盖fly()。

现在我们知道使用继承并不能很好地解决问题,因为鸭子的行为在子类里不断地改变,并且让所有的子类都有这些行为是不恰当的。Flyable接口似乎是个不错的方法,但是Java接口不具有实现代码,所以继承接口无法达到代码的复用。幸运的是,有一个原则,恰好适用此状况。

设计原则:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

我们知道Duck类内的fly() 和quack() 呱呱叫 会随着鸭子的不同而改变,为了要把这个两个行为从Duck类中分开,我们将它们从Duck类中取出来,建立一组新类型来代表每个行为。我们希望一切能有弹性。毕竟,正是因为一开始鸭子行为没有弹性,才让我们走上现在这条路。我们还想能够“指定”行为到鸭子的实例。比方说,我们想要产生一个新的绿头鸭实例,并指定特定“类型”的飞行行为给它。干脆顺便让鸭子的行为可以动态地改变好了。换句话说,我们应该在鸭子类中包含设定行为的方法,这样就可以在“运行时动态地改变绿头鸭的飞行行为。

设计原则:针对接口编程(“针对接口编程”真正的意思是“针对超类型supertype编程”),而不是针对实现编程。

这样鸭子就有一个飞行为,有一个呱呱叫行为。有一个关系相当有趣:每一鸭子都有一个FlyBehavior和一个QuackBehavior,好将飞行和呱呱叫委托给它们代为处理。

3.最后的设计方案为,我们在Duck类中,创建接口FlyBehavior和QuackBehavior的实例,进行操作,将飞行和呱呱叫委托给上面的两个接口处理。

当你将两个或多个类结合起来使用,如同比例一般,这就是组合。这种做法和“继承”不同的地方在于,鸭子的行为不是继承来的,而是和适当的行为对象组合来的。

设计原则:多用组合,少用继承。

这第三种方案就是应用策略模式,定义了算法簇,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

你可能感兴趣的:(策略模式)