软件开发的一个不变的真理---CHANGE
拥抱变化,为变化而生!
设计原则
找出可能发生变化的地方,把它们独立出来单独处理,不要和那些变化的代码混在一起!
把会变化的部分抽取并进行“封装”,以后可以轻松的改动或扩展此部分,而不影响其它不需要变化的部分!
设计原则
针对接口编程,而不是针对实现编程!
针对接口编程,真正的意思是“针对超类型编程”
抽象类、接口
抽象类持有接口的引用
继承
运行时可以动态为子类继承下来的接口指定具体实现类
设计原则
多用组合,少用继承!
将多个类结合起来使用(1个类持有其它类的引用),就是组合(composition)!
这里的其它类便是一组行为(一族算法)的封装
策略模式
定义了算法族,分别封装起来,并让它们可以相互替换。
此模式让算法的变化独立于使用算法的客户。
=======================================================================
不同类型的鸭子和它们的行为
鸭子的父类
package duck;
import duck.fly.FlyBehavior;
import duck.quack.QuackBehavior;
public abstract class Duck {
public Duck() {
}
/**
* 共同的行为,在父类中定义即可
*/
public void swim() {
System.out.println("All duck float!");
}
/**
* 不同子类的display行为不同,只能让子类去实现
*/
public abstract void display();
//==============================
FlyBehavior flyBehavior;//接口,为多态提供了前提
QuackBehavior quackBehavior;//接口,为多态提供了前提
/**
* 委托行为到父类中,这里是关键!
*/
public void performFly() {
flyBehavior.fly();
}
public void perfomQuack() {
quackBehavior.quack();
}
/**
* 对外部暴露修改实现类的入口
* @param flyBehavior
*/
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
具体鸭子---野鸭
package duck;
import duck.fly.impl.FlyWithSwing;
import duck.quack.impl.Quack;
public class MallardDuck extends Duck {
public MallardDuck() {
//对继承下来的属性进行默认初始化
init();
}
private void init() {
flyBehavior = new FlyWithSwing();
quackBehavior = new Quack();
}
public void display() {
System.out.println("I'm a real Mallard Duck");
}
}
具体鸭子---模型鸭
package duck;
import duck.fly.impl.FlyWithSwing;
import duck.quack.impl.MuteQuack;
public class ModelDuck extends Duck {
public ModelDuck() {
//对继承下来的属性进行初始化
init();
}
private void init() {
flyBehavior = new FlyWithSwing();
quackBehavior = new MuteQuack();
}
@Override
public void display() {
System.out.println("I'm a model duck");
}
}
鸭子飞的行为
package duck.fly;
public interface FlyBehavior {
void fly();
}
飞的行为(一)
package duck.fly.impl;
import duck.fly.FlyBehavior;
public class FlyWithSwing implements FlyBehavior {
/**
* 专门针对接口进行实现
* 让特定的行为脱离主线,独立出来,需要新的行为,只需要对外部进行改变即可
*/
@Override
public void fly() {
System.out.println("fly with swing");
}
}
飞的行为(二)
package duck.fly.impl;
import duck.fly.FlyBehavior;
public class FlyNoWay implements FlyBehavior {
/**
* 由行为类去实现接口,而不是让每个子类单独实现一次,提高了代码复用性
* 需要的地方直接引用这个行为类的超类接口即可---解耦,可以灵活改变行为
*/
@Override
public void fly() {
System.out.println("fly no way");
}
}
飞的行为(三)
package duck.fly.impl;
import duck.fly.FlyBehavior;
public class FlyRocketPower implements FlyBehavior {
@Override
public void fly() {
System.out.println("I'm flying with a rocket!");
}
}
鸭子叫的行为
package duck.quack;
public interface QuackBehavior {
void quack();
}
叫的行为(一)
package duck.quack.impl;
import duck.quack.QuackBehavior;
public class Quack implements QuackBehavior {
@Override
public void quack() {
System.out.println("quack");
}
}
叫的行为(二)
package duck.quack.impl;
import duck.quack.QuackBehavior;
public class Squeak implements QuackBehavior {
@Override
public void quack() {
System.out.println("squeak");
}
}
叫的行为(三)
package duck.quack.impl;
import duck.quack.QuackBehavior;
public class MuteQuack implements QuackBehavior {
@Override
public void quack() {
System.out.println("<< Silence >>");
}
}
测试
package test;
import duck.Duck;
import duck.MallardDuck;
import duck.ModelDuck;
import duck.fly.impl.FlyRocketPower;
import duck.quack.impl.Squeak;
public class DuckTest {
public static void main(String[] args) {
Duck mallard = new MallardDuck();
mallard.swim();
mallard.display();
mallard.performFly();
mallard.perfomQuack();
System.out.println("=======break line=======");
Duck model = new ModelDuck();
model.swim();
model.display();
model.performFly();
//动态修改行为
model.setFlyBehavior(new FlyRocketPower());
model.performFly();
model.perfomQuack();
//动态修改行为
model.setQuackBehavior(new Squeak());
model.perfomQuack();
}
}
另一个使用策略模式的例子