定义
? 策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
优点
缺点
? 有一家游戏公司,正在开发一个关于鸭子的游戏,他们将鸭子共有的特征写在了一个父类中。
abstract class Duck{
public void quack() {
System.out.println("嘎嘎");
}
public void swim() {
System.out.println("游泳");
}
public abstract void display();
}
class RubberHeadDuck extends Duck{
@Override
public void quack() {
System.out.println("吱吱");
}
@Override
public void display() {
System.out.println("红头鸭子");
}
}
class GreenHeadDuck extends Duck{
@Override
public void display() {
System.out.println("绿头鸭子");
}
}
public class Problem {
public static void main(String[] args) {
Duck greenHeadDuck = new GreenHeadDuck();
greenHeadDuck.display();
greenHeadDuck.quack();
greenHeadDuck.swim();
}
}
如果不会有需求变化的话,上面这样写是没有任何问题的,但此时要向鸭子的父类中添加一个飞的功能。于是程序员在Duck
类中添加了fly方法。
abstract class Duck{
public void quack() {
System.out.println("嘎嘎");
}
public void swim() {
System.out.println("游泳");
}
public void fly() {
System.out.println("起飞");
}
public abstract void display();
}
但这样修改之后就出现了一些问题,原本在鸭子的子类中,不能飞的鸭子也拥有了飞的属性。这是不符合常理的。此时橡皮鸭只需要重写父类飞的方法,就能看似解决问题。
class RubberHeadDuck extends Duck{
@Override
public void quack() {
System.out.println("吱吱");
}
@Override
public void fly() {
System.out.println("我是假鸭子飞不了");
}
}
但当需求不断变化时,比如再加个木头鸭子,气球鸭子等等,那么我们每加入一个种类,都需要去思考要不要重写父类的飞的方法,这样是很糟糕的。
针对上述问题,我们可以把这两个经常在子类中变化的方法,从父类中分离出来,分成两个接口Flyable,Quackable
。
abstract class Duck {
public void swim() {
System.out.println("游泳");
}
public abstract void display();
}
interface Flyable {
void fly();
}
interface Quackable {
void quack();
}
class RubberHeadDuck extends Duck implements Quackable {
@Override
public void quack() {
System.out.println("吱吱");
}
@Override
public void display() {
System.out.println("红头鸭子");
}
}
class GreenHeadDuck extends Duck implements Quackable, Flyable {
@Override
public void display() {
System.out.println("绿头鸭子");
}
@Override
public void fly() {
System.out.println("起飞");
}
@Override
public void quack() {
System.out.println("嘎嘎");
}
}
// 新增木头鸭子
class WoodenWDuck extends Duck {
@Override
public void display() {
System.out.println("木头鸭子");
}
}
public class Problem3 {
public static void main(String[] args) {
GreenHeadDuck greenHeadDuck = new GreenHeadDuck();
greenHeadDuck.display();
greenHeadDuck.fly();
greenHeadDuck.swim();
}
}
这样做却是比以前更好了,但是以前是:每加入一个新的鸭子角色,程序猿就要判断,这个新鸭子角色是否会飞,是否会叫,不会飞的就重写飞方法,不会叫的就重写叫方法。
现在是:每加入一个新的鸭子角色,程序猿就要判断,这个新鸭子角色是否会飞,是否会叫,不会飞的就不实现Flyable
可扩展接口,不会叫的就不实现Quackable
接口。
此时程序员的任务量仍然很大。仍然要不断的判断新鸭子的属性。fly和quack这两个方法没有一点重用性。
上述的几种解决方案,都存在一定的问题,此时使用策略模式,可以很好的实现方法的重用性。
在策略模式中,具体的鸭子不用去实现具体的飞或者叫的行为,这些行为由特定的类去实现,鸭子类只需要去组合那些特定的实现类。
鸭子飞的行为和叫的方式接口
// 飞的行为
interface FlyBehavior {
void fly();
}
// 叫的行为
interface QuackBehavior {
void quack();
}
飞和叫的具体实现形式
// 飞的具体形式
class FlyWithSwings implements FlyBehavior {
@Override
public void fly() {
System.out.println("用翅膀飞");
}
}
class FlyWithRocket implements FlyBehavior {
@Override
public void fly() {
System.out.println("背着火箭飞");
}
}
class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
System.out.println("不会飞");
}
}
// 叫的具体形式
class QuackWithGaGa implements QuackBehavior {
@Override
public void quack() {
System.out.println("嘎嘎叫");
}
}
class QuackWithZhi implements QuackBehavior {
@Override
public void quack() {
System.out.println("吱吱叫");
}
}
class QuackWithSilence implements QuackBehavior {
@Override
public void quack() {
System.out.println("不会叫");
}
}
将飞的行为和叫的行为加入所有鸭子的父类
Duck
abstract class Duck {
protected FlyBehavior flyBehavior;
protected QuackBehavior quackBehavior;
public void swim() {
System.out.println("游泳");
}
public abstract void display();
// 飞的获取方式
public void performFly() {
flyBehavior.fly();
}
// 叫的获取方式
public void performQuack() {
quackBehavior.quack();
}
}
不同鸭子的不同表现形式,只需在不同的鸭子中去组合那些行为,而无需继承
class QuackWithZhi implements QuackBehavior {
@Override
public void quack() {
System.out.println("吱吱叫");
}
}
class QuackWithSilence implements QuackBehavior {
@Override
public void quack() {
System.out.println("不会叫");
}
}
class RubberHeadDuck extends Duck {
public RubberHeadDuck() {
this.quackBehavior = new QuackWithZhi();
}
@Override
public void display() {
System.out.println("红头鸭子");
}
}
class GreenHeadDuck extends Duck {
public GreenHeadDuck() {
this.flyBehavior = new FlyWithSwings();
this.quackBehavior = new QuackWithGaGa();
}
@Override
public void display() {
System.out.println("绿头鸭子");
}
}
// 新增木头鸭子
class WoodenWDuck extends Duck {
public WoodenWDuck() {
this.flyBehavior = new FlyNoWay();
this.quackBehavior = new QuackWithSilence();
}
@Override
public void display() {
System.out.println("木头鸭子");
}
}
测试
public class StrategyPatten {
public static void main(String[] args) {
Duck woodenWDuck = new WoodenWDuck();
woodenWDuck.performFly();
woodenWDuck.performQuack();
woodenWDuck.display();
Duck greenHeadDuck = new GreenHeadDuck();
greenHeadDuck.performFly();
greenHeadDuck.performQuack();
greenHeadDuck.display();
}
}
不会飞
不会叫
木头鸭子
用翅膀飞
嘎嘎叫
绿头鸭子
总的代码
abstract class Duck {
protected FlyBehavior flyBehavior;
protected QuackBehavior quackBehavior;
public void swim() {
System.out.println("游泳");
}
public abstract void display();
// 飞的获取方式
public void performFly() {
flyBehavior.fly();
}
// 叫的获取方式
public void performQuack() {
quackBehavior.quack();
}
}
// 飞的行为
interface FlyBehavior {
void fly();
}
// 飞的具体形式
class FlyWithSwings implements FlyBehavior {
@Override
public void fly() {
System.out.println("用翅膀飞");
}
}
class FlyWithRocket implements FlyBehavior {
@Override
public void fly() {
System.out.println("背着火箭飞");
}
}
class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
System.out.println("不会飞");
}
}
// 叫的行为
interface QuackBehavior {
void quack();
}
// 叫的具体形式
class QuackWithGaGa implements QuackBehavior {
@Override
public void quack() {
System.out.println("嘎嘎叫");
}
}
class QuackWithZhi implements QuackBehavior {
@Override
public void quack() {
System.out.println("吱吱叫");
}
}
class QuackWithSilence implements QuackBehavior {
@Override
public void quack() {
System.out.println("不会叫");
}
}
class RubberHeadDuck extends Duck {
public RubberHeadDuck() {
this.quackBehavior = new QuackWithZhi();
}
@Override
public void display() {
System.out.println("红头鸭子");
}
}
class GreenHeadDuck extends Duck {
public GreenHeadDuck() {
this.flyBehavior = new FlyWithSwings();
this.quackBehavior = new QuackWithGaGa();
}
@Override
public void display() {
System.out.println("绿头鸭子");
}
}
// 新增木头鸭子
class WoodenWDuck extends Duck {
public WoodenWDuck() {
this.flyBehavior = new FlyNoWay();
this.quackBehavior = new QuackWithSilence();
}
@Override
public void display() {
System.out.println("木头鸭子");
}
}
public class StrategyPatten {
public static void main(String[] args) {
Duck woodenWDuck = new WoodenWDuck();
woodenWDuck.performFly();
woodenWDuck.performQuack();
woodenWDuck.display();
Duck greenHeadDuck = new GreenHeadDuck();
greenHeadDuck.performFly();
greenHeadDuck.performQuack();
greenHeadDuck.display();
}
}
当有新的需求来的时候,比如新增了一种飞的方法,只需在Duck
中添加set方法,然后再实现具体的飞的方式,最后set进Duck
中就可以了。
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
策略模式在很多地方用到,如 Java SE 中的容器布局管理就是一个典型的实例,Java SE 中的每个容器都存在多种布局供用户选择。在程序设计中,通常在以下几种情况中使用策略模式较多。
原文:https://www.cnblogs.com/nuoxin/p/14546018.html