策略模式将可变的部分从程序中抽象分离成算法接口,在该接口下分别封装一系列算法实现并使他们可以相互替换,从而导致客户端程序独立于算法的改变
复合优先于继承,多用组合,少用继承
正文:
这里用鸭子作为实例,鸭子有鸣叫和颜色的特征,这是每只鸭子都有的,我们把飞行作为一个可变特征
第一步:先定义一个接口,用来实现飞行
package com.imooc.pattern.strategy.impl;
import com.imooc.pattern.strategy.FlyingStrategy;
public class FLyWithWin implements FlyingStrategy {
@Override
public void performFly() {
System.out.println("振翅高飞");
}
}
第二步:定义二个类实现飞行接口
会飞:
package com.imooc.pattern.strategy.impl;
import com.imooc.pattern.strategy.FlyingStrategy;
public class FLyWithWin implements FlyingStrategy {
@Override
public void performFly() {
System.out.println("振翅高飞");
}
}
不会飞:
package com.imooc.pattern.strategy.impl;
import com.imooc.pattern.strategy.FlyingStrategy;
public class FlyNoWay implements FlyingStrategy {
@Override
public void performFly() {
System.out.println("我不会飞行!");
}
}
第三步:鸭子主类中实现飞行,和鸣叫和颜色的定义
package com.imooc.pattern.strategy;
public abstract class Duck {
/**
* 鸭子发出叫声
* 通用行为,由超类实现
*/
public void quack(){
System.out.println("嘎嘎嘎 ");
}
/**
* 显示鸭子的外观
* 鸭子的外观各不相同,声明为abstract,由子类实现
*/
public abstract void display();
private FlyingStrategy flyingStrategy;
public void setFlyingStrategy(FlyingStrategy flyingStrategy) {
this.flyingStrategy = flyingStrategy;
}
public void fly(){
flyingStrategy.performFly();
}
}
第四部:子类继承鸭子类,实现各自的特征
绿头鸭:
package com.imooc.pattern.strategy;
import com.imooc.pattern.strategy.impl.FLyWithWin;
public class MallardDuck extends Duck {
public MallardDuck(){
super();
super.setFlyingStrategy(new FLyWithWin());
}
@Override
public void display() {
System.out.println("我的脖子是绿色的");
}
}
红头鸭:
package com.imooc.pattern.strategy;
import com.imooc.pattern.strategy.impl.FLyWithWin;
public class ReadheadDuck extends Duck {
public ReadheadDuck(){
super();
super.setFlyingStrategy(new FLyWithWin());
}
@Override
public void display() {
System.out.println("我的头是红色的");
}
}
橡胶鸭:
package com.imooc.pattern.strategy;
import com.imooc.pattern.strategy.impl.FlyNoWay;
public class RubberDuck extends Duck {
public RubberDuck(){
super();
super.setFlyingStrategy(new FlyNoWay());
}
@Override
public void display() {
System.out.println("我全身发黄,嘴巴发红");
}
public void quack(){
System.out.println("我是小黄鸭");
}
}
大黄鸭:
package com.imooc.pattern.strategy.impl;
import com.imooc.pattern.strategy.Duck;
public class BigYellow extends Duck {
public BigYellow(){
super();
super.setFlyingStrategy(new FlyNoWay());
}
@Override
public void display() {
System.out.println("我身体很大,全身是黄色的");
}
}
这里要注意:因为橡胶鸭和大黄鸭的并不会发出叫声,从而覆盖父类的方法,但是程序员在编写代码的时候经常会忘掉编写覆盖的方法,这是因为编译器并不会提醒是否覆盖,所以可以把叫声这个方法设置成和飞行相同的接口,也就是策略模式。
策略模式的实现:
(1)通过分离变化得出的策略接口Strategy
(2)Strategy的实现类
(3)客户程序有一个Strategy
(4)在客户程序中组装正确的Strategy实现