策略模式:定义算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的用户。
策略模式提倡的编程原则:
- 封装变化
- 多用组合,少用继承
- 针对接口编程,不针对实现编程
代码设计:
1 package pattern.strategy; 2 3 /** 4 * 鸭子的抽象父类 5 * 用于定义一些公共的方法 6 * @author CS_Xiaochao 7 * 8 */ 9 public abstract class Duck { 10 11 FlyBehavior flyBehavior; 12 QuackBehavior quackBehavior; 13 14 /** 15 * 展示当前鸭子所属类型 16 */ 17 public abstract void display(); 18 19 /** 20 * 让鸭子叫出声来 21 */ 22 public String quack(){ 23 return quackBehavior.quack(); 24 } 25 26 /** 27 * 让鸭子飞起来 28 */ 29 public String fly(){ 30 return flyBehavior.fly(); 31 } 32 33 /** 34 * 改变鸭子的飞行行为 35 * @param flyBehavior 36 */ 37 public void setFlyBehavior(FlyBehavior flyBehavior){ 38 this.flyBehavior = flyBehavior; 39 } 40 41 /** 42 * 改变鸭子的叫声行为 43 * @param quackBehavior 44 */ 45 public void setQuackBehavior(QuackBehavior quackBehavior){ 46 this.quackBehavior = quackBehavior; 47 } 48 }
1 package pattern.strategy; 2 3 /** 4 * 鸭子飞行类别接口 5 * @author CS_Xiaochao 6 * 7 */ 8 public interface FlyBehavior { 9 10 String fly(); //飞行方式 11 }
1 package pattern.strategy; 2 3 /** 4 * 鸭子叫声类型接口 5 * @author CS_Xiaochao 6 * 7 */ 8 public interface QuackBehavior { 9 10 String quack(); //叫声方式 11 12 }
1 package pattern.strategy; 2 3 public class FlyWithNoWings implements FlyBehavior { 4 5 @Override 6 public String fly() { 7 return "没有翅膀,但我也能飞~"; 8 } 9 10 }
1 package pattern.strategy; 2 3 public class FlyWithWings implements FlyBehavior { 4 5 @Override 6 public String fly() { 7 return "用翅膀飞~"; 8 } 9 10 }
1 package pattern.strategy; 2 3 public class GagaQuack implements QuackBehavior { 4 5 @Override 6 public String quack() { 7 // TODO Auto-generated method stub 8 return "嘎嘎叫~"; 9 } 10 11 }
1 package pattern.strategy; 2 3 public class ZhizhiQuack implements QuackBehavior { 4 5 @Override 6 public String quack() { 7 // TODO Auto-generated method stub 8 return "吱吱叫~"; 9 } 10 11 }
1 package pattern.strategy; 2 3 public class NoQuack implements QuackBehavior { 4 5 @Override 6 public String quack() { 7 // TODO Auto-generated method stub 8 return "我不会叫~"; 9 } 10 11 }
1 package pattern.strategy; 2 3 /** 4 * 5 * @author CS_Xiaochao 6 * 7 */ 8 public class GeneralDuck extends Duck { 9 10 /** 11 * 构造方法 12 */ 13 public GeneralDuck() { 14 super(); 15 flyBehavior = new FlyWithWings(); 16 quackBehavior = new GagaQuack(); 17 } 18 19 /** 20 * 显示当前鸭子的属性行为 21 */ 22 @Override 23 public void display() { 24 System.out.println("我是一只普通的鸭子: " + super.fly() + " ," + super.quack()); 25 } 26 27 public static void main(String[] args) { 28 29 Duck duck = new GeneralDuck(); 30 duck.display(); 31 32 //改变当前鸭子的行为 33 duck.setFlyBehavior(new FlyWithNoWings()); 34 duck.setQuackBehavior(new ZhizhiQuack()); 35 duck.display(); 36 } 37 38 }
代码设计思想:Duck是一个关于鸭子的抽象类,其中定义了鸭子的一些共同行为、属性,FlyBehavior和QuackBehavior分别是鸭子的飞行行为接口和叫声行为接口,具体的飞行方式和叫声方式通过实现这两个接口,然后在接口声明的方法中进行实现,这样可以在确定调用框架的前提下,随意的修改叫声和飞行方式。而FlyWithWings、FlyWithNoWings这两个类分别实现了飞行方式的接口,定义了具体的飞行方式; GagaQuack、ZhizhiQuack、NoQuack分别实现了叫声方式接口,分别定义了一种叫声方式。Duck类中简单的说就是搭好了调用框架,实现了最通用的调用方式,这样可以保持松耦合。然后在具体的鸭子类中(GeneralDuck),可以指定具体的鸭子的具体的叫声方式和飞行方式,这些方式都是之前已经定义好的,此时只需要选择合适的组件,进行“拼接”即可。
Java I/O中的FilenameFilter接口就是采用了策略模式的思想,通过在实现FilenameFilter接口的accept(File dir, String name)中定义相关规则,可以对文件名进行相关过滤。