策略模式:定义算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。
假如现在要设计一个鸭子类,此鸭子类有三种行为:飞行,叫,以及游泳,但并不是所有的鸭子都会飞行,且鸭子的叫声多种多样。因此飞行和叫声属于变化的部分,将这两部分提取出来进行封装,并将这两种行为组合进鸭子类中。详细代码如下:
/**
* 鸭子父类
*/
public abstract class Duck {
// 为行为接口类型声明两个引用变量,在同一个package中的所有鸭子子类都继承它们
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck(){}
// 将具体的行为委托给行为类
public void performFly(){
flyBehavior.fly();
}
public void performQuack(){
quackBehavior.quack();
}
public void swim(){
System.out.println("All ducks float!");
}
// set新的行为类可随时改变对象的行为
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
/**
* 所有飞行行为的类必须实现的接口
*/
public interface FlyBehavior {
public void fly();
}
/**
* 飞行行为的实现,可以给会飞的鸭子使用
*/
public class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
System.out.println("I cant not fly!");
}
}
/**
* 飞行行为的实现,可以给不会飞的鸭子使用
*/
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("I am fly!");
}
}
/**
* 所有叫声行为的类必须实现的接口
*/
public interface QuackBehavior {
public void quack();
}
/**
* 叫声行为的实现,给呱呱叫的鸭子使用
*/
public class Quack implements QuackBehavior{
@Override
public void quack() {
System.out.println("Quack!");
}
}
/**
* 叫声行为的实现,给吱吱叫的鸭子使用
*/
public class Squeak implements QuackBehavior {
@Override
public void quack() {
System.out.println("Squeak!");
}
}
/**
* 绿头鸭
*/
public class MallerdDuck extends Duck {
// 绿头鸭继承了Duck类,所以具有flyBehavior和quackBehavior实例变量
// 利用构造函数初始化两个实例变量
public MallerdDuck(){
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
}
public void performFly(){
flyBehavior.fly();
}
public void performQuack(){
quackBehavior.quack();
}
public static void main(String[] args) {
Duck duck = new MallerdDuck();
duck.performFly();
duck.performQuack();
duck.setFlyBehavior(new FlyNoWay());
duck.performFly();
duck.swim();
}
}
运行结果如下所示:
I am fly!
Quack!
I cant not fly!
All ducks float!
类结构如下所示:
设计原则:把会变化的部分取出并“封装”起来,好让其他部分不受影响。
设计原则:针对接口编程,而不是针对实现编程。“针对接口编程”的真正意思是“针对超类型编程”。
设计原则:多用组合,少用继承。