设计模式的原则
开闭原则
扩展开放,修改关闭。项目后期维护升级时尽量保证在不修改之前代码的前提下,扩展新功能。
里氏代换原则
这个是对扩展开放的一个具体实现方式-继承。
依赖倒转原则
这个是对扩展开放的一个基础-接口编程。
接口隔离原则
接口隔离,降低类之间的耦合性。
工厂模式
当项目中某个功能的不同产品的业务处理逻辑大部分一致,为了减少重复代码,可使用工厂模式,使得调用者不用操心里面具体的实现逻辑,直接调用具体的产品名称即可。
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就是其中一个。感兴趣可看详细文章 动态代理
开发过程中切切实实的场景还真没见过。若有前辈了解,还请告知一二!