IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 神坑面试题之策略模式 -> 正文阅读

[Java知识库]神坑面试题之策略模式

在这里插入图片描述本图片来自深圳一家独角兽公司

神坑面试题之设计模式

当我看到这题目 觉得很有意思 不就是去除if else if 吗? 这不就是典型的策略模式吗?当然单独靠策略模式是无法全部消除if else if的 还需要靠工厂+策略模式 实现消除if

GOF的《设计模式》著作中认为策略模式可以消除一些条件语句,我对此持怀疑态度。正如上面的例子,虽然由于Context在初始化的时候已经指定了策略实现,在计算逻辑中不需要根据条件选择逻辑分支。但是,客户端代码在初始化Context的时候,如何判断应该传入哪个策略实现呢?其实在客户端代码或者别的地方还是缺少不了条件判断。所以这里消除条件语句,只是针对算法逻辑的条件判断。

2. 策略模式优缺点

那么策略模式的优点是什么了?

2.1 优点

  1. 使用策略模式 可以根据策略接口 定义一系列可供复用的行为和算法;
  2. 调用方只需要持有context 的引用即可 而无需知道具体策略实现 满足迪米特法则;
  3. context在策略的方法之外可以做一些通用的切面逻辑

2.2 缺点

  1. 客户端代码需要知道不同的策略以及如何选择策略。因此可以看到上面的客户端代码有着丑陋的条件判断;
  2. 由于策略类实现同样的接口,所以参数列表要保持一致,但可能并不是所有的策略都需要全部参数

3. 策略模式与工厂模式结合使用

针对第一个缺点。我们可以通过策略模式与工厂模式结合使用来改进。通过进一步封装,消除客户端代码的条件选择
代码如下

package com.zw.design.pattern.behavioral.mianshi;

/****
 * 定义一个动物类的接口 实现策略
 */
public interface IAnimalStrategy {

    public void doPromotion() ;
}
package com.zw.design.pattern.behavioral.mianshi;

/***
 * 定义一个猫的类 实现动物的接口
 */
public class CatStrategy implements IAnimalStrategy {
    @Override
    public void doPromotion() {
        System.out.println("这个是处理猫的类");
    }
}
package com.zw.design.pattern.behavioral.mianshi;

/***
 * 定义一个狗 实现动物策略接口
 */
public class DogStrategy implements IAnimalStrategy {
    @Override
    public void doPromotion() {
        System.out.println("处理dog行为");
    }
}

package com.zw.design.pattern.behavioral.mianshi;

/***
 * 定义一个空策略类 实现动物策略接口
 */
public class EmptyAnimalStrategy implements IAnimalStrategy {
    @Override
    public void doPromotion() {

    }
}

package com.zw.design.pattern.behavioral.mianshi;

/***
 * 这是pig 类实现动物策略接口类
 */
public class PigStrategy implements IAnimalStrategy {
    @Override
    public void doPromotion() {
        System.out.println("这是pig的类");
    }
}

package com.zw.design.pattern.behavioral.mianshi;

import java.util.HashMap;
import java.util.Map;
//这是一个抽象工厂 用来生产所有实现过策略模式的类
public abstract class AnimalStrategyFactory {

    //定义一个 静态的 常量的map 集合
    private final static Map<String, IAnimalStrategy> PROMOTION_STRATEGY_MAP = new HashMap<String, IAnimalStrategy>();

    //定义三个常量 并且是final 而且带分组功能
    private interface PromotionKey{
        String DOG = "dog";
        String PIG = "pig";
        String CAT = "cat";
    }


    /***
     * 根据你传入的key 返回一个具体促销的类 实现可扩展
     * @param promotionKey
     * @return
     */
    public static IAnimalStrategy getPromotionStrategy(String promotionKey){
        IAnimalStrategy promotionStrategy = PROMOTION_STRATEGY_MAP.get(promotionKey);
        // return promotionStrategy == null ? null : promotionStrategy;
        //为了业务 更友好的模式 这里不能返回null   所以定义一个无促销活动的类
        return promotionStrategy == null ? NON_PROMOTION : promotionStrategy;
    }
    //定义一个无促销的活动类
    private static final IAnimalStrategy NON_PROMOTION = new EmptyAnimalStrategy();

    //使用静态代码块进行往map 里面放入值 放入具体的策略的值
    static {
        PROMOTION_STRATEGY_MAP.put(PromotionKey.CAT,new CatStrategy());
        PROMOTION_STRATEGY_MAP.put(PromotionKey.DOG,new DogStrategy());
        PROMOTION_STRATEGY_MAP.put(PromotionKey.PIG,new PigStrategy());
    }
}

package com.zw.design.pattern.behavioral.mianshi;

/***
 * 使用策略模式的客户端 
 */
public class AnimalActivity {
    //放入动物策略的具体类 这里丢入接口 多态思想
    private IAnimalStrategy promotionStrategy;

    public AnimalActivity(IAnimalStrategy promotionStrategy){

        this.promotionStrategy = promotionStrategy;
    }
    //有个具体的行为
    public void executePromotionStrategy(){
        promotionStrategy.doPromotion();
    }

}
//测试
public static void main(String[] args) {
        String petType="dog";
        AnimalActivity animalActivity=new AnimalActivity(
                AnimalStrategyFactory.getPromotionStrategy(petType)
        );
        animalActivity.executePromotionStrategy();
    }

4. 策略模式适用场景

当存在多种逻辑不同,但属于同一类型的行为或者算法时,可以考虑使用策略模式。以此来消除你算法代码中的条件判断。同时让你的代码满足多种设计原则。

很多时候,工厂模式和策略模式都可以为你解决同类问题。但你要想清楚,你想要的是一个对象,还是仅仅想要一个计算结果。如果你需要的是一个对象,并且想用它做很多事情。那么请使用工厂模式。而你仅仅想要一个特定算法的计算结果,那么请使用策略模式。

策略模式属于对象行为模式,而工厂属于创建型模式。策略模式和工厂模式对比如下:
请添加图片描述

5. 小结

策略模式解决的问题是如何封装可供复用的算法或者行为。策略模式满足了单一职责、开闭、迪米特法则、依赖倒转等原则。我们一定想清楚策略模式的适用场景,否则某些时候你会搞不清到底用工厂模式还是策略模式。最后提醒大家,设计模式很多时候都是混合使用,我们不应该局限于使用某一种设计模式来解决问题。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-29 16:10:49  更:2021-11-29 16:11:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:48:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码