zoukankan      html  css  js  c++  java
  • 使用策略模式和工厂模式动态绑定多实现类实例

      摘要: 由于业务场景复杂,一个算法需要开发行为变化多端的多个实现类,然后在系统运行时根据不同场景装载不同的类实例。为了使源码具有更好的可扩展性和可重用性,在借鉴前人处理方法的基础上,介绍在Spring项目中,基于策略模式和工厂模式实现动态匹配相关实现类示例,并调用其中的函数。

    前言

      策略模式(Strategy Pattern)属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的、独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

      策略模式是对算法的包装,是把使用算法的对象和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。下面就以一个示意性的实现讲解策略模式实例的结构。

      主要解决的问题是:在有多种相似算法的情况下,使用 if...else 会增加系统复杂性,降低可扩展性。如果有新的策略,只需要在工厂类加载的包中添加其实现类即可。

      使用场景:一个系统的某个算法接口有许多许多实现类,而它们的不同之处只是它们形形色色的行为。

      策略模式应用实例: 1、诸葛亮的三个锦囊,每一个锦囊都是一个神机妙算的策略。 2、旅行时选择顺风车、飞机等,每一种旅行方式都是一个策略。

      欲了解更多相关知识点请移步《Spring 动态绑定多实现类实例综述》。

    业务场景回顾

      需求描述:定制一个绘图工具,她根据客户端发送的指令可以画出正方形、矩形、圆形和三角形等各种各样的几何图形。例如,当客户端需要绘制三角形的时候,就调用绘制三角形的方法;当需要绘制圆形的时候,就调用绘制圆形的方法。

      策略模式定义了一组算法,把它们一个个封装起来, 并且使它们可相互替换。厂模式用于封装和管理对象的创建,是一种创建型模式。

    /**
     * 画图工具接口
     * @author Wiener
     * @date 2021/1/9
     */
    public interface Shape {
        /**
         * 画图实现方法
         */
        void draw();
    }
    

      定义一个抽象角色ShapeStrategyFactory,由一个接口和一个Map 变量构成。此角色给出所有的具体策略类所需的实现类实例。

    // ---我是分割线---
    
    import com.eg.wiener.service.Shape;
    import org.apache.commons.lang3.StringUtils;
    
    import java.util.HashMap;
    import java.util.Map;
    
    
    /**
     * 策略工厂
     *
     * @author Wiener
     * @date 2021/1/13
     */
    public class ShapeStrategyFactory {
    
        private static Map<String, Shape> SHAPE_REGISTERS = new HashMap<>();
    
        /**
         * 由策略工厂注入Shape接口的不同实现类
         * @param code 实现类编码
         * @param shapeImpl 实现类
         */
        public static void register(String code, Shape shapeImpl) {
            if (StringUtils.isNotBlank(code)) {
                SHAPE_REGISTERS.put(code, shapeImpl);
            }
        }
        public static Shape get(String code) {
            return SHAPE_REGISTERS.get(code);
        }
    }
    
    // ---我是分割线---
    
    import com.eg.wiener.service.Shape;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.PostConstruct;
    
    /**
     * TODO
     *
     * @author Wiener
     * @date 2021/1/7
     */
    @Service
    public class Circle implements Shape {
    
        @Override
        public void draw() {
            System.out.println("Inside Circle::draw() method.");
        }
    
        @PostConstruct
        public void init() {
            ShapeStrategyFactory.register("circle", this);
        }
    
    }
    
    // ---我是分割线---
    import com.eg.wiener.service.Shape;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.PostConstruct;
    
    /**
     * 长方形
     *
     * @author Wiener
     * @date 2021/1/7
     */
    @Service
    public class Rectangle implements Shape {
    
        @Override
        public void draw() {
            System.out.println("Inside Rectangle::draw() method.");
        }
        @PostConstruct
        public void init() {
            ShapeStrategyFactory.register("rectangle", this);
        }
    }
    // ---我是分割线---
    import com.eg.wiener.service.Shape;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.PostConstruct;
    
    /**
     * TODO
     *
     * @author Wiener
     * @date 2021/1/7
     */
    @Service
    public class Square implements Shape {
        @Override
        public void draw() {
            System.out.println("Inside Square::draw() method.");
        }
        @PostConstruct
        public void init() {
            ShapeStrategyFactory.register("square", this);
        }
    }
    // ---我是分割线---
    import com.eg.wiener.service.Shape;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.PostConstruct;
    
    /**
     * 三角形
     *
     * @author Wiener
     * @date 2021/1/7
     */
    @Service
    public class Triangle implements Shape {
        @Override
        public void draw() {
            System.out.println("Inside Triangle::draw() method.");
        }
        @PostConstruct
        public void init() {
            ShapeStrategyFactory.register("triangle", this);
        }
    }
    

      这段代码的关键是ShapeStrategyFactory类,它是一个策略工厂,里面定义了一个全局的map变量 SHAPE_REGISTERS,在所有Shape的实现类中注册当前实例到map中,然后在调用的地方通过ShapeStrategyFactory类的Shape get(String code)根据code从map获取画图类实例即可。测试用例如下:

        //通过注解把不同实现类的bean注入变量,与策略工厂做对比
        @Autowired
        private Map<String, Shape> beanMap;	
        @GetMapping("/ssDraw")
        public void ssDraw(String code) {
            beanMap.get(code).draw();		
            ShapeStrategyFactory.get(code).draw();
        }
    

      我们也可以通过注解把不同实现类的bean注入变量,与策略工厂对比后发现,两者可以完成同样的工作,但是前者代码工作量更少,主要是不需要在每个实现类加入注册类的非业务代码。

    结束语

      欢迎点赞阅读,一同学习交流;若有疑问,请在文章下方留下你的神评妙论!

    Reference


      读后有收获,小礼物走一走,请作者喝咖啡。

    赞赏支持

  • 相关阅读:
    C# 冒泡排序
    C# IO流 File.Exists,Directory.Exists, File.Create,Directory.CreateDirectory
    UGUI 哪些显示在前方的问题
    UGUI Image血条或者进度条效果
    Unity 切换场景的时候让某个游戏对象不消失
    C# string型的转换成float型的
    Json 解析Json
    logging模块

    模块和包
  • 原文地址:https://www.cnblogs.com/east7/p/14390809.html
Copyright © 2011-2022 走看看