介绍
概念:策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式的让算法的变化独立于使用算法的客户。
使用场景:有多种算法相似的情况,可以用来替换if else(替换以后虽然没有if,但是LZ认为更麻烦,增加很多类)
优点:算法之间可以随意替换,使用策略模式以后,代码的扩展性很好
缺点:策略类太多,很繁琐
正文
一个简单的例子,带你进入神奇的策略模式。
有个很简单的需求,有一个狗父类,它有一个eat()和call()方法,一个是吃,一个是叫。不同种类的狗可能叫和吃都不一样,所以,我们需要重写父类的方法。
父类
public class Dog {
public Dog() {
}
//狗叫
public void call(){
System.out.println("汪汪");
}
//吃东西
public void eat(){
System.out.println("吃肉");
}
}
子类
子类是柯基狗种类,他吃肉,但是柯基狗有自己独特的叫声,所以重写call()方法
public class Koji extends Dog{
private String name;
public Koji(String name) {
this.name = name;
}
@Override
public void call(){
System.out.println(name+"汪汪,汪汪汪");
}
}
客户端类
public class Client {
public static void main(String[] args) {
Dog koji = new Koji("旺财");
koji.call();
koji.eat();
}
}
打印输出:
旺财汪汪,汪汪汪
吃肉
总结
漂亮,很完美,我们还用到了多态,以后再来一只柯基狗,起个名字就可以汪汪了,因为我们暂且同一种的狗叫声一样。我们还可以增加别的种类的狗,只需要继承狗父类,重写方法就可以了,很简单。
需求变更
但是这样写有没有什么问题,你肯定会说没问题,但是,有个这样的需求,随着科技的发展,我们有了人工智障机械狗,他会叫,但是不能吃饭喝水,只需充电就行了,我们还能让他继承狗父类吗?
显然不能,我们默认狗都会叫会吃东西,这怎么办呢?
救世主登场
我们先看策略模式的类图
我们把行为封装成接口,子类需要什么行为直接实现接口就行,父类具有对接口的调用,子类和接口的耦合度降低。
改造原有设计
父类就是我们的Context
public class Dog {
ICallInterface callInterface;
IEatInterface eatInterface;
public Dog() {
}
//狗叫
public void call(){
callInterface.call();
}
//吃东西
public void eat(){
eatInterface.eat();
}
}
我们以吃东西为例
接口
public interface IEatInterface {
public void eat();
}
具体策略角色
public class EatMeatImpl implements IEatInterface{
@Override
public void eat() {
System.out.println("吃肉");
}
}
public class EatBoneImpl implements IEatInterface{
@Override
public void eat() {
System.out.println("吃骨头");
}
}
public class NoEatImpl implements IEatInterface{
@Override
public void eat() {
System.out.println("我是机械的,我什么也不吃");
}
}
我们实例化一个机械狗出来,它继承狗父类,但是它不吃东西
public class MechanicalDog extends Dog{
public MechanicalDog() {
//这里给父类指明自己调用哪个算法
eatInterface = new NoEatImpl();
}
}
再实例化一条柯基狗,他只吃肉
public class Koji extends Dog{
public Koji() {
eatInterface = new EatMeatImpl();
}
}
一个简单的策略模式搭成了,每个子类可以调用不同的行为来满足自己的需求,还可以随意切换实现类。
写一个客户端测试一下
public class Client {
public static void main(String[] args) {
Dog koji = new Koji();
koji.eat();
Dog mechanicalDog = new MechanicalDog();
mechanicalDog.eat();
}
}
吃肉
我是机械的,我什么也不吃