美文网首页
策略模式(封装可以互换的行为,并使用委托来决定要使用哪一个)

策略模式(封装可以互换的行为,并使用委托来决定要使用哪一个)

作者: 钉某人 | 来源:发表于2017-11-06 20:08 被阅读0次
源码地址 https://github.com/DingMouRen/DesignPattern
策略模式.png
  • Context------用来操作策略的对象
  • Stragety------策略的抽象
  • ConcreteStragetyA、ConcreteStragetyB ------具体策略的实现
定义

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

使用场景
  • 许多相关的类仅仅是具体实现不同。
  • 处理同一个问题,但是有不同的算法实现。
  • 一个类定义了多种行为,并且这些行为在这个类的操作中会以if-else或者switch-case的形式出现时。
协作
  • Strategy与Context相互作用来实现选定的算法。当算法被调用时,Context可以将该算法所需要的所有数据都传递给该Strategy。或者,Context可以将自身作为一个参数传递给Strategy操作。这就让Strategy在需要时可以回调Context
  • Context将它的客户的请求转发给它的Strategy。客户通常创建并传递一个ConcreteStrategy对象给该Context,这样客户端仅需要与Context交互。通常有一系列的ConcreteStrategy类可供客户端从中选择。
举个栗子

一个学生要获取到数字6,他有多种算法。

一般做法:假设在类Student中实现获取到数字6的算法getNumberSix(),如果老师要求使用相加的方式来实现,那么我们就用相加的方式来实现;没多久老师又让我们用相乘的方式来实现,好吧,我们再写相乘方式的算法;又没多久老师让我再以相减的方式来实现,我们又得回到Student类添加if-else,又对代码进行修改,违背了OO的开闭原则,设计的类应该是对扩展开放,对修改关闭。

 //获取到数字6
    public void getNumberSix(String str){
        if (str.equals("相加")){
            addMethod();//相加的方式获取到数字6
        }else if (str.equals("相乘")){
            multiMethod();//相乘的方式获取到数字6
        }else if (str.equals("相减")){
            subtractMethod();//通过相减的方式获取到数字6
        }
    }

思考:我们想让Student类一旦编写结束,尽量不要再修改它,获取到数字6的算法有多种,怎么办呢?考虑到java的封装与多态,我们可以将算法封装成一个类,再向上抽象,抽象成一个接口,这个接口有一个方法(获取数字6的算法),每一个实现类都要实现这个方法。我们通过聚合的方式,将接口通过类Student的构造函数作为一个成员变量置于Student类中,在Student类的getNumberSix()方法中调用接口的方法。接口实现类负责具体算法的实现,比如相加获取6,相乘获取6,Studnet类要获取数字6的话,就在创建Student时传入接口实现类,java多态自动向上转型,传入的类型都是接口类型的,然后在调用getNumberSix()时,java的向下转型和运行时类型判断就起到了关键作用,这时调用的方法就是当时传入的接口实现类的方法。如果老师还想要其他的算法要求的话,只要实现接口的方法,传入新的算法就行了,这样就非常容易扩展了,也不用修改Student类。为了可以动态的更换算法,我们添加一个set方法,就可以实现动态更换算法了。

//学生
public class Student {
    private Stragety stragety;//策略的抽象,也可以称作泛化

    public Student(Stragety stragety) {
        this.stragety = stragety;
    }

    /**
     * 获取数字6
     */
    public void getNumberSix(){
        int result = stragety.calculate();
        System.out.println(result == 6 ? "获取的数字正确":"获取的数字不正确,获取到的数字是"+result);
    }

    /**
     * 可以动态的更换策略
     * @param stragety
     */
    public void setStragety(Stragety stragety) {
        this.stragety = stragety;
    }

}

//策略的抽象
public interface Stragety {
    int calculate();//获取到数字6的方法抽象
}
//具体策略的实现:相加
public class StragetyAdd implements Stragety {
    /**
     * 具体算法的实现:通过相加的方式获取到数字6
     * @return
     */
    @Override
    public int calculate() {
        int result = 0;
        for (int i = 0; i < 6; i++) {
            result += 1;
        }
        return result;
    }
}
//具体策略的实现:相乘的
public class StargetyMultiply implements Stragety{
    /**
     * 具体算法的实现:通过相乘的方式获取到数字6
     * @return
     */
    @Override
    public int calculate() {
        int result = 2 * 3;
        return result;
    }
}

使用

public static void main(String[] args) {
        //创建对象
        Student student = new Student(new StragetyAdd());
        //获取到数字6
        student.getNumberSix();
        //动态更换策略
        student.setStragety(new StargetyMultiply());
        student.getNumberSix();
    }
总结

优点

  • 结构清晰,使用简单
  • 耦合度相对较低
  • 扩展方便
  • 操作封装后,数据更加安全
    缺点
  • 随着策略的增加,子类会变得繁多

相关文章

  • 策略模式(封装可以互换的行为,并使用委托来决定要使用哪一个)

    Context------用来操作策略的对象 Stragety------策略的抽象 ConcreteStrage...

  • 策略模式

    一、策略模式的定义 策略模式:定义一系列算法,封装每个算法,并使他们可以互换,不同的策略可以让算法独立于使用它们的...

  • 设计模式(十六)简短小结

    装饰者模式,包装一个对象,以提供新的行为。 状态模式,封装了基于状态的行为,并使用委托在行为之间切换。 迭代器模式...

  • 设计模式之策略模式

    一、定义 定义一系列算法,封装每个算法,并使它们可以互换。策略模式可以让算法独立于使用它的客户端。 二、结构实现 ...

  • PHP中常见的五种设计模式

    策略模式 策略模式是对象的行为模式,用意是对一组算法的封装。动态的选择需要的算法并使用。 策略模式指的是程序中涉及...

  • 策略模式

    策略模式,一个类的行为或算法可以再运行时更改,属于行为型模式。 定义一系列算法,封装每一个算法并使他们可以互换,策...

  • Kotlin对SP使用的封装

    为了更易于使用SharedPreferences,使用Koltin的委托模式来对SP进行封装 1. 定义委托类 2...

  • 设计模式-策略模式

    策略模式 定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。将共同的行为封装成策略接口,不同策略实现类只...

  • 策略模式

    定义 策略模式使用的就是java中继承和多态,定义不同的算法,将它们封装起来,让他们之间可以互换。 代码实现 创建...

  • 02- 策略模式(Strategy Pattern)

    策略模式(Strategy Pattern) 概述 策略模式,是一种将策略封装类,并采取组合的方式,让策略使用者进...

网友评论

      本文标题:策略模式(封装可以互换的行为,并使用委托来决定要使用哪一个)

      本文链接:https://www.haomeiwen.com/subject/zgxrmxtx.html