刚刚开始学习,使用一个书里简单的小例子帮助记忆。
策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
我们先来看一个简单的案例
主类
//完全解耦,只关联了接口,没有任何实例化,靠子类去实现
public class Food {
public Eat eatBehavior; //接口
public void performEat(){ //代理实现接口,测试的时候直接调用该方法即可
eatBehavior.eat();
}
}
子类
public class Noodle extends Food {
public Noodle(){
eatBehavior = new Noodle_imp(); //实例化接口
}
}
接口
public interface Eat {
void eat();
}
实例化接口
public class Noodle_imp implements Eat {
@Override
public void eat() {
System.out.println("吃面条");
}
}
测试
public static void main(String[] args) {
Food f = new Noodle(); //使用多态,noodle子类中有构造方法实例化接口方法
f.performEat(); //调用父类方法,此时已经实例化接口方法
}
输出:
吃面条
这样全面解耦以后,可以起无数个子类来继承主类,只要每个子类内部实例化各个接口方法即可。例如做饭的接口,购买的接口等等,主类只要再起几个代理方法,子类构造方法实例化这些接口即可。
下面就是headFirst里面的一个案例,比较全面,复制到项目里面跑一下就知道精妙之处了。
一、主类
public class Duck {
public FlyBehavior flyBehavior;//飞行行为
public QuackBehavior quackBehavior;//叫声行为
public void swim(){
System.out.println("我会游泳");
}
public void display(){
System.out.println("我是白色的");
}
public void performQuack(){//叫声代理方法
quackBehavior.quack();
}
public void performFly(){//飞行代理方法
flyBehavior.fly();
}
public void setFlyBehavior(FlyBehavior flyBehavior) {//项目中可以动态修改飞行
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
二、行为接口
- 1、飞行行为接口
public interface FlyBehavior{
void fly();
}
- 2、叫声行为接口
public interface QuackBehavior {
void quack();
}
三、行为实现
- 1、不能飞
public class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
System.out.println("不能飞");
}
}
- 2、可以飞
public class FlyWithings implements FlyBehavior {
@Override
public void fly() {
System.out.println("飞行");
}
}
- 3、嘎嘎叫
public class Quack implements QuackBehavior{
@Override
public void quack() {
System.out.println("嘎嘎叫");
}
}
- 4、吱吱叫
public class Squeak implements QuackBehavior {
@Override
public void quack() {
System.out.println("吱吱叫");
}
}
四、子类
public class MalardDuck extends Duck{
public MalardDuck(){
quackBehavior = new Quack();//使用多态,实例化一个“嘎嘎叫”的鸭子
flyBehavior = new FlyWithings();//不会飞
}
@Override
public void display() {
System.out.println("我是绿色的");
}
}
五、测试
public class test {
public static void main(String[] args) {
Duck d = new MalardDuck();
d.performQuack();
d.performFly();
d.swim();
d.display();
}
}
如果有新的鸭子,比如一个模型鸭子,不会叫也不会飞,这个时候只要再写一个类即可。
为了能动态生成模型鸭子,在Duck父类里面加入了set方法
//实现的时候
public class test {
public static void main(String[] args) {
/*Duck d = new MalardDuck();
d.performQuack();
d.performFly();
d.swim();
d.display();*/
Duck d = new ModelDuck();//模型鸭子
d.performQuack();
d.swim();
d.display();
d.setFlyBehavior(new FlyRocketPowered());//飞行模式,需要一个实现接口的方法,该类实现了fly接口的方法
d.performFly();
}
}
控制台输出:
嘎嘎叫
我会游泳
我是模型鸭
我能使用火箭飞行
这样,如果又有新的鸭子,新的方法(比如出生地,模型鸭子没有,则父类Duck再代理一个出生地方法)再生成别的类即可,不影响现有的方法