『策略模式』定义了算法族,分别封装起来,让它们之间可以互相替换, 此模式让算法的变化独立于使用算法的客户。例子来源于Head First Design Pattern。
Duck 是一个抽象类,Duck下面有一些子类,所有的Duck都会游泳,swim方法定义在Duck类中,所有的子类都会继承这个方法,因此在调用swim方法时所有的子类都会显示同样的特性。display()方法也定义在Duck中,但是需要子类的重载,每一个不同的Duck在调用dispaly()时候都会展示不同的特性。
需要说明的就是performFly()这个方法,为什么不像其他方法一样定义为fly()呢?这是因为并非所有的Duck的fly()都显示同样的特性,有些duck可能根本不会fly,这是和swim()方法的不同点。那为什么不在子类中重载fly()的实现呢?这是因为可能有很大一部分Duck的子类所表现的fly()特性是一致的,如果都重载这个实现的话代码无法共享。因此我们把这部分共享的代码拿出来来单独考虑。我们可以把每种不同的策略单独做一个类,针对这个fly()的特性,可能有两种实现,一种是flyWithWings,一种是flyNoWay。但是针对Duck这个类来说,我们都暴露相同的接口。因此只需要定义一个接口flyBehavior就可以了,flyWithWings和flyNoWay都继承这个接口,实现fly()方法。
perfomQuack()和performFly()类似,不再赘述。
1. 抽象类Duck
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public void display() {
}
public void swim(){
System.out.println("I am swimming");
}
public void performFly(){
flyBehavior.fly();
}
public void performQuack(){
quackBehavior.quack();
}
public void setFlyBehavior(FlyBehavior flyBehavior){
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior){
this.quackBehavior = quackBehavior;
}
}
2. 具体类MallarDuck
public class MallarDuck extends Duck{
public MallarDuck(){
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
}
public void display(){
System.out.println("I am Mallar Duck!");
}
}
3. 接口flyBehavior
public interface FlyBehavior {
public void fly();
}
4. 具体策略类 FlyWithWings
public class FlyWithWings implements FlyBehavior{
public void fly(){
System.out.println("I am flying!");
}
}
5. 具体策略类FlyNoWay
public class FlyNoWay implements FlyBehavior{
public void fly(){
System.out.println("I can't fly!");
}
}
6.其他类,如RedHeadDuck, RubberDuck,QuackBehavior 略
7. 测试代码
Duck[] ducks = {new MallarDuck(), new RedHeadDuck(), new RubberDuck()};
for(Duck d: ducks){
d.display();
d.swim();
d.performFly();
d.performQuack();
System.out.println();
}
最后附源代码
Duck 是一个抽象类,Duck下面有一些子类,所有的Duck都会游泳,swim方法定义在Duck类中,所有的子类都会继承这个方法,因此在调用swim方法时所有的子类都会显示同样的特性。display()方法也定义在Duck中,但是需要子类的重载,每一个不同的Duck在调用dispaly()时候都会展示不同的特性。
需要说明的就是performFly()这个方法,为什么不像其他方法一样定义为fly()呢?这是因为并非所有的Duck的fly()都显示同样的特性,有些duck可能根本不会fly,这是和swim()方法的不同点。那为什么不在子类中重载fly()的实现呢?这是因为可能有很大一部分Duck的子类所表现的fly()特性是一致的,如果都重载这个实现的话代码无法共享。因此我们把这部分共享的代码拿出来来单独考虑。我们可以把每种不同的策略单独做一个类,针对这个fly()的特性,可能有两种实现,一种是flyWithWings,一种是flyNoWay。但是针对Duck这个类来说,我们都暴露相同的接口。因此只需要定义一个接口flyBehavior就可以了,flyWithWings和flyNoWay都继承这个接口,实现fly()方法。
perfomQuack()和performFly()类似,不再赘述。
1. 抽象类Duck
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public void display() {
}
public void swim(){
System.out.println("I am swimming");
}
public void performFly(){
flyBehavior.fly();
}
public void performQuack(){
quackBehavior.quack();
}
public void setFlyBehavior(FlyBehavior flyBehavior){
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior){
this.quackBehavior = quackBehavior;
}
}
2. 具体类MallarDuck
public class MallarDuck extends Duck{
public MallarDuck(){
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
}
public void display(){
System.out.println("I am Mallar Duck!");
}
}
3. 接口flyBehavior
public interface FlyBehavior {
public void fly();
}
4. 具体策略类 FlyWithWings
public class FlyWithWings implements FlyBehavior{
public void fly(){
System.out.println("I am flying!");
}
}
5. 具体策略类FlyNoWay
public class FlyNoWay implements FlyBehavior{
public void fly(){
System.out.println("I can't fly!");
}
}
6.其他类,如RedHeadDuck, RubberDuck,QuackBehavior 略
7. 测试代码
Duck[] ducks = {new MallarDuck(), new RedHeadDuck(), new RubberDuck()};
for(Duck d: ducks){
d.display();
d.swim();
d.performFly();
d.performQuack();
System.out.println();
}
最后附源代码