设计模式- 策略模式

Posted adventure.Li

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式- 策略模式相关的知识,希望对你有一定的参考价值。

一、什么是设计模式

  1. 为什么需要设计模式

(1)基本概念

设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

(2)提高复用

在软件日益复杂化,从科学计算需要到实际应用的需要。软件的复杂度越来越高,对后期维护的需要也日益凸显,因此好的复用是十分必要,成为OO的设计目标。

  1. 设计模式四要素
  • 名称 name
  • 问题problem:意图,上下文,适用场景
  • 解决方案:UML结构图、抽象代码(关键),职责与协作
  • 效果:结果和折中
  1. 设计的基本原则
  • 单一职责原则(SRP)
  • 信息与行为集中
  • 针对接口编程
  • 接口最小化/接口分离原则(LSP)
  • Demeter原则
  • 里氏替换原则(SLP)
  • 组合复用原则
  • 开闭原则OCP
  • 依赖倒置DIP

设计的整体目标 高内聚 低耦合,对于类的联系分为 方法、类(都为一个模块),因此主要就分为 方法调用,类之间的相互访问,父类与子类继承的关系 ;而对应面向对象编程 主要研究类的关系 ,那么分为 关联(一个对象持有另外一个对象的引用) 和 继承 。因此导致访问耦合和继承耦合,以上原则中 针对接口编程、接口最小化、迪米特原则(只与自己密切相关的发生联系,而级联调用则是明显地违背此原则) 都属于访问耦合,里氏替换和组合复用属于 继承耦合。对于单一职责和信息与行为集中 属于 提高内聚,而 OCP和DIP则是为复用,提升维护 变更设计的提出的概念原则(理解信息隐藏与封装的内涵)。

二、策略模式

  1. 定义

在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

  1. 示例1 (交通灯)

事件 描述:现有这样一个场景,交通灯在白天,夜晚,深夜等不同时间段,而设置的红绿灯提示不同,在白天因为行人较多流量大,则绿灯为30s,夜晚和深夜依次为20s,10s。

该场景中:明细的出现同一个行为(即绿灯的显示时间长度)具有多变性。适用策略模式。在此之前,来看看传统写法。

(1)使用swicth判断 传统写法

class TranfficEvent{
   int greenShowTime;
   void excute(char type){
      swicth '1'://..
      swicth '2'://..
      swicth '3'://..
   }
   //....
   void setTime()
}

以上代码:出现了控制耦合,人为定义控制,同时提升了维护复用的难度,因此进行下面的修改。

(2)改进 (继承)

public class TrafficContext {
    int showTime;
    TrafficContext(){
        showTime = 10;//默认 10
    }
    void execute(){
        System.out.println("start....");
        for(int i=1;i<1000;i++)
        {
            if(i%showTime==0){
                System.out.println("show green...");
            }
            try {
                Thread.sleep(1000);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

public class DayTrafficContext extends TrafficContext{
    DayTrafficContext(){
        this.showTime = 30;
    }
    @Override
    void execute() {
        super.execute();
    }
}

public class NightTrafficContext extends TrafficContext{
    NightTrafficContext(){
        this.showTime = 10;
    }
    @Override
    void execute() {
        super.execute();
    }
}

public class TestDriver {
    public static void main(String[]args){
        TrafficContext context1 = new DayTrafficContext();
        context1.execute();
    }
}

该方法:优点的确实现了很好的复用,在不修改原代码的基础进行了拓展,但是存在的问题时 继承不能处理变换

(3)继续改进 (策略模式)

注意点:context类(完备类),单个行为独立出来 (不能离开完整的类,同时该方法具有多变性)

public class TrafficContext {
       int showTime;
       Strategy strategy;
       public void changeStrategy(Strategy strategy){
           System.out.println("change ..");
           this.strategy = strategy;
           showTime = strategy.getShowTime();
       }
       public void execute(){

        System.out.println("start....");
        for(int i=1;i<1000;i++)
        {
            if(i%showTime==0){
                System.out.println("show green...");
            }
            try {
                Thread.sleep(1000);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

public interface Strategy {
    int getShowTime();
}

public class DayStrategy implements Strategy{
    @Override
    public int getShowTime() {
        return 30;
    }
}

public class NightStrategy implements Strategy{
    @Override
    public int getShowTime() {
        return 10;
    }
}

效果:

  • 可修改性和可复用性增强
  • 易理解性减低,更加复杂(好的方面消除多分支判断,坏的方面:逻辑分散)

提升:

  1. 若多个行为多变呢? 则设置多个不同策略。(list)
  2. N个方法多变,且强绑定。(使用信息隐藏,抓住什么东西多变)
  3. 若属性多变呢? 则把属性放出去。

深入分析

可变更:信息隐藏

  • 实现的可修改性
  • 实现的可扩展性
  • 实现灵活性

体现什么样的设计原则??

  • SRP
  • 组合代替继承
  • OCP、LSP、DIP

违反:信息与行为集中原则

以上是关于设计模式- 策略模式的主要内容,如果未能解决你的问题,请参考以下文章

Redis实现分布式锁(设计模式应用实战)

设计模式策略模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

代码片-策略模式+工厂模式

代码片-策略模式+工厂模式

代码片-策略模式+工厂模式

代码片-策略模式+工厂模式