设计模式学习之——策略模式

本文通过鸭子类的例子,详细介绍了策略模式的应用场景及其实现过程。策略模式将一系列可互换的算法封装,允许它们独立于客户端变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用设计模式最好的方式:把设计模式装进脑袋里面,然后在你的设计和已有的应用中,寻找何处可以使用它们。

设计模式是一种前人踩过的坑,之后总结下来的编程经验,也就是说这样做通常比较好。我们学习这种经验,以便在我们以后的项目中避免很多问题。

应用场景

举个例子,一个鸭子类。
原来有一些行为,现在要加入飞行的方法。那么怎么做才是最好的解决方法呢?
注意,并不是所有的鸭子都能飞。
所以直接在父类里面加进去飞行方法是有问题的。
这个飞行动作 是可变的,并不是每种都有的。

  • 涉及到维护的时候,为了复用而使用继承,结局并不好。
  • 对超类进行局部修改,影响层面是全局的。

如果使用接口,那么虽然解决了只有会飞的鸭子才能飞的问题,但是呢,却造成了原来所有的实现都要修改和大量的代码冗余。

解决办法

每次新的需求来了,需要改变的部分,就是要封装起来的部分。

核心思想:把会变化的部分取出并封装起来 ,以便以后可以轻易地改动或者扩展此部分,而不影响其他不需要变化的部分。

把飞行的行为作为一个借口,依附于超级鸭子父类

鸭子的子类使用接口所表示的行为,不会绑死在鸭子的子类里面。

下面是全部代码
首先是 duck类

public abstract class Duck {
public Duck(){

};
FlyBehavior flyBehavior;

public void setFlyBehavior(FlyBehavior flyBehavior) {
    this.flyBehavior = flyBehavior;
}

public void performFly(){
    flyBehavior.fly();
}

public void swim(){
    System.out.println("所有鸭子都可以游泳");
}

}

接下来是飞行接口。

public interface FlyBehavior {
public void fly();

}

实现飞行借口的类

public class FlyWithNoWay  implements FlyBehavior{

@Override
public void fly() {
    System.out.println("我不会飞!");

}

}

另一个

public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
    System.out.println("翅膀飞");
}

}

最后我们真正用到的鸭子

public class MallardDuck extends Duck {

public MallardDuck() {
    flyBehavior=new FlyWithWings();

}

}

测试类

public class TestFly {
    public static void main(String[] args) {
        Duck duck=new MallardDuck();
        duck.performFly();
        duck.setFlyBehavior(new FlyWithNoWay());
        duck.performFly();
    }
}

运行结果

  • 翅膀飞
  • 我不会飞!

维护以及优点

假如说以后加入一个喷气鸭子,怎么办呢?

public class FlywithRocket implements FlyBehavior {

    @Override
    public void fly() {
        System.out.println("喷气飞");
    }
}
public class TestFly {
public static void main(String[] args) {
    Duck duck=new MallardDuck();
    duck.performFly();
    duck.setFlyBehavior(new FlywithRocket());//喷气飞
    duck.performFly();
}

}

那么假如要加入一个新的行为,比如说eat ,这个行为至少橡皮鸭子就是不能吃的。

所以首先要新写一个eat的接口。

public interface EatBehavior {
public void eat();

}

实现接口的具体吃法

public class EatWithGlass implements EatBehavior {
    @Override
    public void eat() {
        System.out.println("吃草");
    }   
}
public class EatWithNothing implements EatBehavior {
@Override
public void eat() {
    System.out.println("什么都不吃");
}

}

接下来修改原来的DUCK类

public abstract class Duck {
public Duck(){

};
FlyBehavior flyBehavior;
EatBehavior eatBehavior;

public void setFlyBehavior(FlyBehavior flyBehavior) {
    this.flyBehavior = flyBehavior;
}

public void setEatBehavior(EatBehavior eatBehavior) {
    this.eatBehavior = eatBehavior;
}



public void performFly(){
    flyBehavior.fly();
}

public void performEat(){
    eatBehavior.eat();
}

public void swim(){
    System.out.println("所有鸭子都可以游泳");
}

}

测试类
public class TestEat {

public static void main(String[] args) {
    Duck duck=new MallardDuck();
    duck.setEatBehavior(new EatWithNothing());
    duck.performEat();
    duck.setEatBehavior(new EatWithGlass());
    duck.performEat();
}

}

这样就可以动态的改变新的属性了。

那么最关键的一点来了,我们的子类感觉到了变化吗?
没有,实现的子类的代码没有修改。

也就说这样代码就写活了。

针对借口编程,而不是针对实现编程。

而需要不同的吃的行为只要传进去不同的eat的接口的实现类就好了。

多用组合,少用继承。

好了,这就是策略模式。

定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值