策略模式概述
定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于算法的客户。
面向对象编程的特性
1)抽象
2)封装
3)多态
4)继承
原则
1、(封装变化)找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混合在一起
2、(针对接口编程,而不是针对实现编程)即多去实现接口少用继承类的方式,因为Java语言是单继承允许多实现
ps:在oo系统中,类一般都是由状态(实例变量)又有方法,但是在这个例子中,行为也可以作为一个类,因为行为也可以有实例变量,有它的状态和方法记录飞行行为的属性
3、(多用组合,少用继承)其实也是针对第二条的一个补充,使用组合建立系统具有很大的弹性,不仅可以将算法族封装成类,更可以“在运行时动态改变它的行为”,只要组合的行为对象符合正确的接口标准
实现的Demo
假设有一个场景,设计一个鸭子类,让鸭子可以拥有叫或者飞的属性(属性可以有外观,飞,叫),鸭子可以有橡皮鸭,青头鸭,机器鸭,以及我们所能想象的鸭,如果我们把飞和叫的属性直接与鸭子类耦合在一起,那就设计不同鸭子的时候都要重写这些方法,可能有些鸭子不会叫或者不会飞,不利于代码的维护,所以我们可以把经常改动的方法抽取出来作为一个行为类。
鸭子类:
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public abstract void display();
public void performFly()
{
flyBehavior.fly();
}
public void performQuack()
{
quackBehavior.quack();
}
public void swim()
{
System.out.println("所有鸭子都会游泳");
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
机器鸭类(继承了鸭子类,也拥有鸭子类的实例变量和对应的方法):
public class RobotDuck extends Duck {
@Override
public void display()
{
System.out.println("我是机器鸭,有着机器的外壳");
}
public RobotDuck()
{
flyBehavior = new FlyNoWay();
quackBehavior = new RobotQuack();
}
}
飞的行为接口
public interface FlyBehavior {
void fly();
}
飞的行为实现类(火箭动力):
public class FlyByRocket implements FlyBehavior{
@Override
public void fly() {
System.out.println("用火箭动力实现飞");
}
}
飞的行为实现类(不会飞)
public class FlyNoWay implements FlyBehavior {
@Override
public void fly(){
System.out.println("我不会飞");
}
}
叫的行为接口
public interface QuackBehavior
{
void quack();
}
叫的实现类(机器鸭)
public class RobotQuack implements QuackBehavior {
@Override
public void quack() {
System.out.println("机器鸭叫");
}
}
叫的实现类(不会叫)
public class MuteQuack implements QuackBehavior {
@Override
public void quack() {
System.out.println("我不会叫");
}
}
测试方法
public class Main {
public static void main(String[] args) {
Duck robotDuck = new RobotDuck();
robotDuck.display();
robotDuck.performFly();
robotDuck.performQuack();
robotDuck.setFlyBehavior(new FlyByRocket());
robotDuck.performFly();
}
}
总结
1)这样一个鸭子类就不会不依赖于它的行为,把行为和鸭子类抽取了出来,每次如果要实现行为,就使用它的代理去找到它对应的行为实现类,实现了代码解耦合,用了set方法,也更容易去改变一个鸭子的行为特征。
2)每一个鸭子都有一个FlyBehavior和QuackBehavior,好比就是将飞行和叫的行为委托给它们代为处理