设计模式在开发实践中的运用

Posted 上官云霆

tags:

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

一、 背景

项目业务较为复杂,而且会随着时间的推移,不断新增需求,代码也只能在此处进行不断堆叠,各种业务逻辑掺杂在一块,不具有条理性,最终代码变得臃肿,没人能够维护。

二、优劣势

优势劣势
1.更具有模块化。举例,模块1用于构建对象,模块2用于分配处理策略…
2.更便于维护;
1.理解设计模式,需要一些学习时间;

三、设计模式

1. 策略模式

定义:

在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。

适用业务类型:

在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。 将这些算法封装成一个一个的策略类,任意地替换。
当有四个请求对应四种不同处理策略时,
1.我们需要在同一个类A中进行至少四次if…else;
2.如果需要新增处理策略时,会在类A中增加if…else造成当前类A不断变大臃肿,复杂度变高;
3.当某个处理策略发生变化时,我们需要在当前类A的if中进行修改,不同处理策略可能需要不同变量,但这些变量都会存放在类A,类A会变得难以维护,而且改动类A代码时,极有可能改坏其他处理策略;

举例

旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略;

import org.springframework.beans.factory.InitializingBean;

/**
 * @Description
 */
public interface MappingStrategy extends InitializingBean 

    String mappingValueTransfer();
    // 从映射策略上下文中获取对应策略中
    @Override
    default void afterPropertiesSet() 
        MappingContext.map.put(getMappingValueTransferCode(), this);
    

    // 每个实现类中重写该方法,用于得到映射策略的枚举值
    Integer getMappingValueTransferCode();


import java.util.HashMap;
import java.util.Map;

/**
 * @Description 映射上下文
 */
public class MappingContext 
    public static Map<Integer, MappingStrategy> map = new HashMap<>();
    // 获取对应的映射策略
    public static String executeStrategy
            (Integer mappingValueTransfer) 
        return map.get(mappingValueTransfer).mappingValueTransfer();
    

import org.springframework.stereotype.Component;

/**
 * @Description 策略一
 */
@Component
public class MappingValueTransferOne implements MappingStrategy 


    @Override
    public String mappingValueTransfer() 
        return "执行策略一";
    

    @Override
    public Integer getMappingValueTransferCode() 
        return new Integer(1);
    
    

import org.springframework.stereotype.Component;

/**
 * @Description 策略二
 */
@Component
public class MappingValueTransferTwo implements MappingStrategy 


    @Override
    public String mappingValueTransfer() 
        return "执行策略二";
    

    @Override
    public Integer getMappingValueTransferCode() 
        return new Integer(2);
    



import org.springframework.stereotype.Component;

/**
 * @Description 策略三
 */
@Component
public class MappingValueTransferThree implements MappingStrategy 


    @Override
    public String mappingValueTransfer() 
        return "执行策略三";
    

    @Override
    public Integer getMappingValueTransferCode() 
        return new Integer(3);
    



优劣势:

优点缺点
1、算法可以自由切换;
2、避免使用多重条件判断;
3、扩展性良好;
1、策略类会增多;
2、所有策略类都需要对外暴露;

2.建造者模式

定义:

建造者模式使用多个简单的对象一步一步构建成一个复杂的对象。

适用业务类型:

当我们需要进行"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。

举例

1.乐高积木,每块积木都是单独的个体,通过将多块积木组合,拼装初始化一个复杂的乐高成品;

优劣势:

优点缺点
1、建造者独立,易扩展
2、便于控制细节风险。
1、产品必须有共同点,范围有限制
2、如内部变化复杂,会有很多的建造类。

样例

直接参考即可 https://www.runoob.com/design-pattern/builder-pattern.html

3.抽象工厂模式

定义:

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

适用业务类型:

系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
当我们要做两种处理A和B,且A,B两种处理是存在类似性,处理都较为复杂,每个小细节都存在一些差异时,我们可以利用工厂模式分为不同的处理对象进行处理。

举例:

游戏换皮肤,一整套一起换;

优劣势:

缺点
抽象工厂模式 当一个产品族中的多个对象被设计成一起工作时,
它能保证客户端始终只使用同一个产品族中的对象。 产品族扩展非常困难,要增加一个系列的某一产品,
既要在抽象的 Creator 里加代码,又要在具体的里面加代码。

样例

直接参考即可 https://www.runoob.com/design-pattern/abstract-factory-pattern.html

4.工厂模式

定义:

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

适用业务类型:

我们明确地计划不同条件下创建不同实例时。让其子类实现工厂接口,返回的也是一个抽象的产品。

举例:

1、您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现

优劣势:

优点缺点
1.解耦:对象的创建和使用分离
2.减少代码重复、创建蔓延,降低维护成本:对于创建较为复杂的对象,可以减少代码重复、降低维护成本
1.每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加

样例

直接参考即可 https://www.runoob.com/design-pattern/factory-pattern.html
或者

import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;

/**
 * @description 返回码处理
 */
public class ResponseUtils 
    // 系统报错
    private static int SERVER_ERROR = 99999;
    // 非法参数
    private static int INVALID_REQUEST = 30001;

    public static <T> T fail(T response, Throwable ex) 
        if (ex instanceof NullPointerException) 
            return fail(SERVER_ERROR, "SERVER_ERROR", response);
        
        if (ex instanceof IllegalArgumentException) 
            return fail(INVALID_REQUEST, "INVALID_REQUEST", response);
        
        return fail(SERVER_ERROR, "SERVER_ERROR", response);
    


    public static <T> T fail(int responseCode, String responseDesc, T instance) 
        return fillResponse(responseCode, responseDesc, instance);
    


    private static <T> T fillResponse(int responseCode, String responseDesc, T response) 
        Field responseCodeField = ReflectionUtils.findField(response.getClass(), "responseCode", Integer.class);
        Field responseDescField = ReflectionUtils.findField(response.getClass(), "responseDesc", String.class);

        if (responseDescField == null || responseCodeField == null) 
            return response;
        

        ReflectionUtils.makeAccessible(responseCodeField);
        if (ReflectionUtils.getField(responseCodeField, response) == null) 
            ReflectionUtils.setField(responseCodeField, response, responseCode);
        

        ReflectionUtils.makeAccessible(responseDescField);
        if (ReflectionUtils.getField(responseDescField, response) == null) 
            ReflectionUtils.setField(responseDescField, response, responseDesc);
        
        return response;
    

参考资料

https://www.runoob.com/design-pattern/design-pattern-intro.html

以上是关于设计模式在开发实践中的运用的主要内容,如果未能解决你的问题,请参考以下文章

结合工程实践选题调研分析同类软件产品

结构型设计模式在公司项目中的运用实践

敏捷开发之Scrum方法运用

#yyds干货盘点#-设计模式分享-抽象工厂模式

抽象工厂模式

抽象工厂模式