java设计模式

设计模式的原则

开闭原则

扩展开放,修改关闭。项目后期维护升级时尽量保证在不修改之前代码的前提下,扩展新功能。

里氏代换原则

这个是对扩展开放的一个具体实现方式-继承。

依赖倒转原则

这个是对扩展开放的一个基础-接口编程。

接口隔离原则

接口隔离,降低类之间的耦合性。

工厂模式

当项目中某个功能的不同产品的业务处理逻辑大部分一致,为了减少重复代码,可使用工厂模式,使得调用者不用操心里面具体的实现逻辑,直接调用具体的产品名称即可。

java 复制代码
@Service
@Slf4j
public class TypeFactory {

    public void cal(String type){
        //根据不同的产品类型处理不同业务逻辑 TODO
        
    }
}

当不同产品有自己的service类文件时,也可通过工厂找到对应的service后调用其方法

工具类 ApplicationContextHelper

java 复制代码
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @Auther: lr
 * @Date: 2024/8/9 10:33
 * @Description: 根据bean名称获取对应的类
 */
@Component
public class ApplicationContextHelper implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public static Object getBean(String className) throws BeansException, IllegalArgumentException {
        if (className == null || className.length() <= 0) {
            throw new IllegalArgumentException("className is null!");
        }

        String beanName = null;
        if (className.length() > 1) {
            beanName = className.substring(0, 1).toLowerCase() + className.substring(1);
        } else {
            beanName = className.toLowerCase();
        }
        return applicationContext != null ? applicationContext.getBean(beanName) : null;
    }
}

工厂类 TypeFactory

java 复制代码
@Service
@Slf4j
public class TypeFactory {

    public TypeInterface getType(String type){
        String beanName = type + "Service";
        try {
            Object instance = ApplicationContextHelper.getBean(beanName);
            return (TypeInterface)instance;
        } catch (Exception e) {
            log.error("{}未找到对应类",type,e);
            throw e;
        }
    }
}

接口 TypeInterface

java 复制代码
/**
 * @Auther: lr
 * @Date: 2024/8/7 15:29
 * @Description: 接口
 */
public interface TypeInterface {

    void cal();
}

理财产品 BondService

java 复制代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @Auther: lr
 * @Date: 2024/8/7 15:08
 * @Description: 理财产品的service
 */
@Service
@Slf4j
public class BondService implements TypeInterface{

    public void cal(){
        log.info("理财产品计算....");
    }
}

定期贷款 FixedDepositService

java 复制代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @Auther: lr
 * @Date: 2024/8/7 15:09
 * @Description: 定期贷款的service
 */
@Service
@Slf4j
public class FixedDepositService implements TypeInterface{

    public void cal(){
        log.info("定期贷款计算....");
    }
}

controller 根据type类型调用对应的方法

java 复制代码
import com.example.demo.service.TypeFactory;
import com.example.demo.service.TypeInterface;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Auther: lr
 * @Date: 2024/8/7 15:20
 * @Description:
 */
@RestController
@Slf4j
@RequestMapping("/testFactory")
public class TestFactoryController {

    @Autowired
    private TypeFactory typeFactory;

    @RequestMapping("/getCal")
    public String getCal(@RequestParam("type") String type){
        TypeInterface typeInterface = typeFactory.getType(type);
        typeInterface.cal();
        return "success";
    }
}

测试

调用接口 /testFactory/getCal?type=Bond 可以看到后台日志打印

单例模式

懒汉式

人很懒,等到饿了才去找食物。类加载时不会初始化,只有用的时候才会new实例对象。

java 复制代码
public class SingleBean {
    //未进行初始化
    private static SingleBean instance;
    private SingleBean (){}
    //调用时才会new对象
    public static synchronized SingleBean getInstance() {
        if (instance == null) {
            instance = new SingleBean();
        }
        return instance;
    }
}

饿汉式

人勤快,屯食物待饿了就吃。类加载时初始化实例对象,后续直接用。

java 复制代码
public class SingleBean {
    //初始化
    private static SingleBean instance=new SingleBean();
    private SingleBean (){}
    public static SingleBean getInstance() {
        return instance;
    }
}
  • 懒汉式由于在方法内new对象,若多线程同时进来,发现找不到对象,都去new对象,会造成数据覆盖现象。而饿汉式在类加载时就已经初始化实例对象。所以与懒汉式相比,饿汉式是线程安全的;
  • 懒汉式由于出现多线程调用情况,会在方法上加锁(synchronized),保证同一时间只有一个进程调用,此时执行效率会降低。所以饿汉式的执行效率比懒汉式快;
  • 由于饿汉式在类初始化时加载,内存占用会浪费空间。所以饿汉式的内存情况比懒汉式占用量大且耗内存;

这篇文章的解决方法二 使用的则是懒汉式方式,可试着用饿汉式解决。一般会使用饿汉式解决

代理模式

代理模式很常见,spring的aop就是其中一个。感兴趣可看详细文章 动态代理

开发过程中切切实实的场景还真没见过。若有前辈了解,还请告知一二!

相关推荐
爱读源码的大都督几秒前
为什么有了HTTP,还需要gPRC?
java·后端·架构
Lucky_Turtle20 分钟前
【Java Xml】Apache Commons Digester3解析
xml·java·apache
聪明的笨猪猪39 分钟前
Java Redis “缓存设计”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
FIavor.39 分钟前
我发送给Apifox是http://localhost:9002/goods/getByUserName?name=张三 为什么会是500哪里错了?
java·服务器·网络协议·http
ID_1800790547340 分钟前
京东获取整站实时商品详情数据|商品标题|数据分析提取教程
java·开发语言
微露清风1 小时前
系统性学习C++-第五讲-内存管理
java·c++·学习
计算机毕业设计木哥1 小时前
计算机毕业设计选题推荐:基于SpringBoot和Vue的快递物流仓库管理系统【源码+文档+调试】
java·vue.js·spring boot·后端·课程设计
235161 小时前
【LeetCode】146. LRU 缓存
java·后端·算法·leetcode·链表·缓存·职场和发展
聪明的笨猪猪2 小时前
Java Redis “运维”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
FIavor.2 小时前
怎么办这是Apifox里执行http://localhost:9002/goods/getByUserName?name=“张三“为什么我改了还是500?
java·网络·网络协议·http