zoukankan      html  css  js  c++  java
  • 策略模式(Strategy)---行为型

    1 基础知识

    定义:定义了算法家族,分别封装起来,让他们可以相互替换,此模式让算法的变化不会影响到使用算法的用户(应用层)。特征:可以替换掉大量的if else语句

    本质:分离算法,选择实现。

    使用场景:

    (1)出现有许多相关的类,仅仅是行为有差别的情况下,可以使用策略模式来使用多

    个行为中的一个来配置一个类的方法,实现算法动态切换。

    (2)出现同一个算法,有很多不同实现的情况下,可以使用策略模式来把这些“不同的实现”实现成为一个算法的类层次。

    (3)需要封装算法中,有与算法相关数据的情况下,可以使用策略模式来避免暴露这些跟算法相关的数据结构

    (4)出现抽象一个定义了很多行为的类,并且是通过多个 it-else语句来选择这些行为的情况下,可以使用策略模式来代替这些条件语句。 

    优点:符合开闭原则;避免使用多重条件转移语句;提高算法的保密性和安全性。 缺点:客户端必须知道所有的策略类,并自行决定使用哪一个策略类;产生多个策略类。

    2 代码示例

    使用场景:假设慕课网的视频课程在不同的时间段会有不同的打折活动。那么可以认为这些不同的打折活动便是不同的策略。

    打折策略接口:PromotionStrategy 

    public interface PromotionStrategy {
        void doPromotion();
    }

     满减策略:ManJianPromotionStrategy

    public class ManJianPromotionStrategy implements PromotionStrategy{
    
        public void doPromotion() {
            System.out.println("满减促销,满200-20元");
        }
    }

    立减策略:LiJianPromotionStrategy

    public class LiJianPromotionStrategy implements PromotionStrategy {
    
        public void doPromotion() {
            System.out.println("立减促销,课程的价格直接减去配置的价格");
        }
    }

    返现策略:FanXianPromotionStrategy

    public class FanXianPromotionStrategy implements PromotionStrategy{
    
        public void doPromotion() {
            System.out.println("返现促销,返回的金额存放到慕课网用户的余额中");
        }
    }

    打折活动:PromotionActivity

    public class PromotionActivity {
        private PromotionStrategy promotionStrategy;
        //构造器注入
        public PromotionActivity(PromotionStrategy promotionStrategy) {
            this.promotionStrategy = promotionStrategy;
        }
    
        public void executePromotionStrategy(){
            promotionStrategy.doPromotion();
        }
    }

    应用层:Test

    public class Test {
        public static void main(String[] args) {
            PromotionActivity promotionActivity618 = new PromotionActivity(new LiJianPromotionStrategy());
            PromotionActivity promotionActivity1111 = new PromotionActivity(new FanXianPromotionStrategy());
            
            //不同阶段采用不同的策略
            promotionActivity618.executePromotionStrategy();
            promotionActivity1111.executePromotionStrategy();
        }
    }

     在上面应用层时预先定义好了,但如果没有预先定义好,那么可能就会有如下的情况:

    public static void main(String[] args) {
            PromotionActivity promotionActivity = null;
    
            String promotionKey = "LIJIAN";
    
            if ("LIJIAN".equals(promotionKey)){
                System.out.println(123);
                promotionActivity = new PromotionActivity(new LiJianPromotionStrategy());
            }else if ("MANJAN".equals(promotionKey)){
                System.out.println("其他策略");
            }
            //...其他策略
            
           promotionActivity.executePromotionStrategy();
        }

    通过不断的进行if else 判断来调整不同的策略,但这种情况肯定不是我们想要的。因此可以采用工厂模式来消除if else

    策略工厂:PromotionStrategyFactory

    public class PromotionStrategyFactory {
    
        //定义一个map集合来保存不同策略
        private static Map<String,PromotionStrategy> Promotion_Strategy_Map = new HashMap<String, PromotionStrategy>();
        static {
            Promotion_Strategy_Map.put(PromotionKey.LIJIAN,new LiJianPromotionStrategy());
            Promotion_Strategy_Map.put(PromotionKey.MANJIAN,new ManJianPromotionStrategy());
            Promotion_Strategy_Map.put(PromotionKey.FANXIAN,new FanXianPromotionStrategy());
        }
    
        //构造器私有
        private PromotionStrategyFactory(){
    
        }
        //定义一个无促销的策略
        private static PromotionStrategy NON_PROMOTION = new EmptyPromotionStrategy();
    
        public static PromotionStrategy getPromotionStrateg(String promotionKey){
            PromotionStrategy promotionStrategy = Promotion_Strategy_Map.get(promotionKey);
            //当为空时直接返回无促销策略
            return promotionStrategy == null ? NON_PROMOTION : promotionStrategy;
        }
    
        //在声明常量的时候起到了一个分组的作用,默认即为final的不可更改
        private interface PromotionKey{
            String LIJIAN = "LIJIAN";
            String FANXIAN = "FANXIAN";
            String MANJIAN = "MANJIAN";
        }
    }

    无促销类:EmptyPromotionStrategy  这个类只是为了对应为空时的情况

    public class EmptyPromotionStrategy implements PromotionStrategy{
    
        public void doPromotion() {
            System.out.println("无促销");
        }
    }

    应用层:Test

    public static void main(String[] args) {
            //外界传过来的
            String promotionKey = "LIJIAN";
            //采用工厂进行实例化
            PromotionActivity promotionActivity = new PromotionActivity(PromotionStrategyFactory.getPromotionStrateg(promotionKey));
    
            promotionActivity.executePromotionStrategy();
     }

     3

    4 相关模式

    (1)策略模式和状态模式

        这两个模式从模式结构上看是一样的,但是实现的功能却是不一样的。状态模式是根据状态的变化来选择相应的行为,不同的状态对应不同的类,每个状态对应的类实现了该状态对应的功能,在实现功能的同时,还会维护状态数据的变化。这些实现状态对应的功能的类之间是不能相互替换的。策略模式是根据需要或者是客户端的要求来选择相应的实现类,各个实现类是平等的,是可以相互替换的。另外策略模式可以让客户端来选择需要使用的策略算法:而状态模式一般是由上下文,或者是在状态实现类里面来维护具体的状态数据,通常不由客户端来指定状态。

    (2)策略模式和模板方法模式

      这两个模式可组合使用,如同前面示例的那样。模板方法重在封装算法骨架;而策略模式重在分离并封装算法实现。

    (3)策略模式和享元模式

        这两个模式可组合使用。策略模式分离并封装出一系列的策略算法对象,这些对象的功能通常都比较单一,很多时候就是为了实现某个算法的功能而存在。因此,针对这一系列的、多个细粒度的对象,可以应用享元模式来节省资源,但前提是这些算法对象要被频繁地使用,如果偶尔用一次,就没有必要做成享元了。 

    0

  • 相关阅读:
    第一阶段-坑爹猴
    终于做出来了
    一天就制作成了这些
    累成狗做出来的
    一周的学习,组合起来的成就
    刚刚出炉的搜狗浏览器最新版本
    自己动手设计了一下下百度首页
    数论:卢卡斯定理(求组合数)
    数据结构:ST表模板(可维护区间RMQ)
    快读和快写(可以使用__int128)
  • 原文地址:https://www.cnblogs.com/youngao/p/11352414.html
Copyright © 2011-2022 走看看