定义:定义了算法族(行为),分别封装起来,让他们之间可以互相替换。此模式让算法的变化独立于使用算法的客户。
下面看个例子的代码
public abstact class Duck{
FlyBehavior flybehavior;//为行为接口类型声明两个引用变量
QuackBehavior quackBehavior;//切记这是接口或者父类
public Duck{}
public abstract void display();
publci void performFly(){
flybehavior.fly();//委托给行为类
}
publci void performQuack(){
quackBehavior.fly();//委托给行为类
}
public void setFlyBehavior( FlyBehavior fb){
flybehavior=fb;//可以动态设置行为
}
public void setQuackBehavior( QuackBehavior qb){
quackBehavior=qb;
}
publci void swim(){
System.out.println("所有的鸭子都会游泳")
}
}
现在制造一个新的鸭子类型测试一把
public class ModelDuck extengs Duck{
public ModelDuck(){
flyBehavior=new FlyNoWay();
quackBehavior=new Quack();//这个接口没有写懒其实和上面的一样
}
public void display(){
System.out.println("我是火箭动力鸭子");
}
}
public class DuckTest{
Duck model = new ModelDuck();
model.performFly();//重点来了这个会被委托给 flyBehavior对象,(也是FlyNoWay实例),
//该对象是在模型鸭子构造器中设置的
model.setFlyBehavior(new FlyRocketPowered());
//这会调用继承的set方法把火箭动力行为设置到模型鸭子中
model.perforFly();
//输出结果,我不会飞,我是火箭动力鸭子
}
回顾一下自己的当时愚蠢思路:开发一个模拟鸭子游戏,可以游泳swim,叫quack。后来又加入了fly飞。在这里理所当然的想到设计一个父类Duck鸭子,里面有不同的方法让子类去继承实现。但是,并不是所有的鸭子都会飞。又想到了把行为设计成接口,比如Flyable,有需要飞的鸭子再去实现。但是,java接口不具有实现代码,无法复用代码,这意味着无论何时需要修改某个行为,你必须得往下追踪并在每一个类中修改它。所以:找出应用中变化的部分,把他们独立出来,不要和那些不需要变化的代码混在一起。以前的做法是:行为来自Duck超类的具体实现或是继承某个接口并由子类自行实现。这两种做法都是依赖于“实现”。所以:
针对接口编程,而不是针对实现编程。利用多态。程序可以针对超类编程,执行时会根据实际状况执行到真正的行文,不会被绑死在超类的行为上。也就是上面代码Duck类中的两个实例变量。鸭子现在会将飞行和呱呱叫的动作委托给别人处理。这也正是
有一个比是一个更好-------多用组合,少用继承。