策略者模式
首先介绍几个设计模式里面的原则,后面会一 一提到。
1,将代码中变的部分与不变的部分分离开来,独立出来。
2,针对接口编程。
3,多组合少继承。
<本文以及之后的文章是作者阅读 HeadFirst 设计模式 阅读笔记,以及个人见解>
本模式开始于一个鸭子模型。有一只鸭子类 Duck 他会飞 fly() 游泳swim() 叫quack() ......
class Duck{
fly(){}
quack(){}
swim(){}
.......
}
他有很多子类,比如说鸭子1,鸭子2,鸭子3都是继承于他,并且拥有他的这些技能(fly quack swim)。但是现在我要新加入只鸭子,但是它不会飞,他继承 Duck 类显然不是很明知的,如果我将 Duck类中的fly方法 去掉不就可以了,但这有需要在他的其他子类中重新写fly方法,也不利于代码的复用。
class Duck1 extends Duck{
}
class Duck2 extends Duck{
}
class Duck3 extends Duck{
}
....
class Duck4 extends Duck{
/* 这是一只旱鸭不会飞*/
}
于是想到一个办法是将fly方法提出来,即我开始说的第一条原则。放到一个FlyAble接口中去,让那些会飞的鸭子实现他。但这也并非是一个好的主意应为仍然没有实现的代码的复用,很多鸭子飞的行为可能是一样的。
这里仍然使用FlyAble接口只是该接口的实现不是由子类来做的,而是我们专门写一个或多个类来实现FlyAble接口,这样做有很好弹性,你想下,fly行为可能有很多不同的实现,因为很多会飞的鸭子飞的方式可能有所差别,但也有相同的。对于相同的我们写一个实现类即可,这实现了代码的复用,对于不同的飞行行为,我们可以写其他的实现类,这使得增加一个新的飞行行为更加有弹性。
interface FlyAble{
fly();
}
FlyFreedom implements FlyAble{
fly(){
System.out.println("fly of freedom !!!");
}
}
FlyHappy implements FlyAble{
fly(){
System.out.println("fly of happy !!!");
}
}
FlySad implements FlyAble{
fly(){
System.out.println("fly of sad!!!");
}
}
FlyNoway implements FlyAble{
fly(){
System.out.println("fly of canot!!!");
}
}
那么那些会飞的鸭子怎么去使用这些行为呢?总不能直接继承这些实现类吧!我们知道java里面只能继承一个类,子类已经继承了Duck了,所以行不通。我们是不是可以直接在子类里面写一个FlyAble变量叫做flyBehavior,然后给他赋予不同的实现类,如果不会飞的鸭子我们给他FlyNoway(不会飞的类)。
class Duck1 extends Duck{
FlayAble flyBehavior;
public Duck1(){
flyBehavior = new FlyHappy();
}
}
...
class Duck4 extends Duck{
FlayAble flyBehavior;
public Duck4(){
flyBehavior = new FlyNoway();
}
}
这里我们其实可以优化一下的,比如说我们可以将 变量flyBehavior方在Duck类里面,这不是减少了代码的量,而且一定程度上降低了耦合度,子类代码中没有直接写flyBehavior变量,并且我们将该变量的初始化也写在Duck类里面,并且使用setter方给子类来改变,flyBehavior 变量让他们获得自己想要的飞行行为。注意对于不会飞的鸭子我们可以将flyBehavior = new FlyNoway(),d当他调用fly方法时候将直接显示“我不会飞”。
class Duck{
FlyAble flyBehavior;
public void Duck(){
flyBehavior = new FlyHappy();
}
//子类可以动态的改变飞行行为 这里FlyAble接口有多态带来的好处
public void setFlyBehavior(FlyAble f){
this.flyBehavior = f;
}
fly(){
flyBehavior.fly();
}
quack(){}
swim(){}
.......
}
总结:策略者模式,对于同一种算法(行为 类比前面的飞行行为)有不同的实现,我们将其分类出来,从而从中选择我们想要的算法(行为),进行组合。分离(变化的与不变的分离) -> 选择(我们需要的) -> 组合(组合到具体的实现类中)。