- 抽象工厂模式介绍
- 抽象工厂模式的实战
- 不使用抽象工厂模式的写法
- 使用抽象工厂模式的写法
- 定义适配接口
- 创建不同集群缓存的实现
- 创建代理类
- 抽象工厂在Spring中的应用
抽象工厂模式是创建其他工厂的模式. 一个标准(接口)有不同的实现.
抽象工厂模式的实战案例是采用系统中有不同的缓存服务. 对不同的缓存服务做适配.
不使用抽象工厂模式的写法创建tutorials-5.0-0 模块 pom中如下
4.0.0
org.example
1.0-SNAPSHOT
tutorials-5.0-0
com.alibaba
fastjson
1.2.62
junit
junit
4.12
test
org.slf4j
slf4j-api
1.7.5
org.slf4j
jcl-over-slf4j
1.7.5
ch.qos.logback
logback-classic
1.0.9
slf4j-api
org.slf4j
创建一个RedisUtils 缓存工具类, 实现缓存的增删改查功能.
public class RedisUtils {
private Logger logger = LoggerFactory.getLogger(RedisUtils.class);
private Map dataMap = new ConcurrentHashMap();
public String get(String key) {
logger.info(" redis 获取数据 key: {}", key);
return dataMap.get(key);
}
public void set(String key, String value) {
logger.info("redis 写入数据 key: {} val:{}", key, value);
dataMap.put(key, value);
}
public void set(String key, String value, long timeout, TimeUnit timeUnit) {
logger.info("redis 写入数据 并设置过期时间 key:{} val:{} timeout:{} timeUnit:{}", key, value, timeout, timeUnit.toString());
dataMap.put(key, value);
}
public void del(String key) {
logger.info("redis 删除数据 key: {}", key);
dataMap.remove(key);
}
}
CacheService 缓存服务的接口
public interface CacheService {
String get(final String key);
void set(String key, String value);
void set(String key, String value, long timeout, TimeUnit timeUnit);
void del(String key);
}
缓存服务的实现类CacheServiceImpl
public class CacheServiceImpl implements CacheService {
private RedisUtils redisUtils = new RedisUtils();
public String get(String key) {
return redisUtils.get(key);
}
public void set(String key, String value) {
redisUtils.set(key, value);
}
public void set(String key, String value, long timeout, TimeUnit timeUnit) {
redisUtils.set(key, value, timeout, timeUnit);
}
public void del(String key) {
redisUtils.del(key);
}
}
EGM 类实现EGM的缓存服务
public class EGM {
private Logger logger = LoggerFactory.getLogger(EGM.class);
private Map dataMap = new ConcurrentHashMap();
public String gain(String key) {
logger.info("EGM获取数据 key: {}", key);
return dataMap.get(key);
}
public void set(String key, String value) {
logger.info("EGM 写入数据 key: {} , val : {}", key, value);
dataMap.put(key, value);
}
public void setEx(String key, String value, long timeout, TimeUnit timeUnit) {
logger.info("EGM 写入数据 key:{} val:{} timeout:{} timeUnit:{}", key, value, timeout, timeUnit.toString());
dataMap.put(key, value);
}
public void delete(String key) {
logger.info("egm 删除数据 key: {}", key);
dataMap.remove(key);
}
}
IIR 实现IIR的缓存服务
public class IIR {
private Logger logger = LoggerFactory.getLogger(IIR.class);
private Map dataMap = new ConcurrentHashMap();
public String get(String key) {
logger.info("IIR获取数据 key: {}", key);
return dataMap.get(key);
}
public void set(String key, String value) {
logger.info("IIR写入数据 key:{} val:{}", key, value);
dataMap.put(key, value);
}
public void setExpire(String key, String value, long timeout, TimeUnit timeUnit) {
logger.info("IIR写入数据 key:{} val:{} timeout:{} timeUnit:{}", key, value, timeout, timeUnit.toString());
dataMap.put(key, value);
}
public void del(String key) {
logger.info("IIR删除数据 key:{}", key);
dataMap.remove(key);
}
}
tutorials-5.0-1 创建改模块, 用于在不使用设计模式时的缓存兼容. pom如下: 引用了tutorials-5.0-0
mydesign-study
org.example
1.0-SNAPSHOT
4.0.0
tutorials-5.0-1
com.alibaba
fastjson
1.2.62
junit
junit
4.12
test
org.slf4j
slf4j-api
1.7.5
org.slf4j
jcl-over-slf4j
1.7.5
ch.qos.logback
logback-classic
1.0.9
slf4j-api
org.slf4j
org.example
1.0-SNAPSHOT
tutorials-5.0-0
创建CacheService接口
public interface CacheService {
String get(final String key, int redisType);
void set(String key, String value, int redisType);
void set(String key, String value, long timeout, TimeUnit timeUnit, int redisType);
void del(String key, int redisType);
}
创建CacheServiceImpl 类如下 , 用if else去判断不同的实现缓存
package com.thc.design.cuisine.impl;
import com.thc.design.CacheService;
import com.thc.design.RedisUtils;
import com.thc.design.matter.EGM;
import com.thc.design.matter.IIR;
import java.util.concurrent.TimeUnit;
/**
* 类名称:CacheServiceImpl
* @author: taohongchao
* 创建时间:2022/3/16 10:33
*/
public class CacheServiceImpl implements CacheService {
private RedisUtils redisUtils = new RedisUtils();
private EGM egm = new EGM();
private IIR iir = new IIR();
public String get(String key, int redisType) {
if (1 == redisType) {
return egm.gain(key);
}
if (2 == redisType) {
return iir.get(key);
}
return redisUtils.get(key);
}
public void set(String key, String value, int redisType) {
if (1 == redisType) {
egm.set(key, value);
return;
}
if (2 == redisType) {
iir.set(key, value);
}
}
public void set(String key, String value, long timeout, TimeUnit timeUnit, int redisType) {
if (1 == redisType) {
egm.setEx(key, value, timeout, timeUnit);
}
if (2 == redisType) {
iir.setExpire(key, value, timeout, timeUnit);
}
redisUtils.set(key, value, timeout, timeUnit);
}
public void del(String key, int redisType) {
if (1 == redisType) {
egm.delete(key);
return;
}
if (2 == redisType) {
iir.del(key);
return;
}
redisUtils.del(key);
}
}
创建测试类ApiTest
public class ApiTest {
@Test
public void test_cacheService() {
CacheService cacheService = new CacheServiceImpl();
cacheService.set("user_name1", "周杰伦", 1);
String value = cacheService.get("user_name1", 1);
System.out.println("测试结果: "+ value);
cacheService.set("user_name2", "周润发", 2);
String value2 = cacheService.get("user_name2", 2);
System.out.println("测试结果: "+ value2);
}
}
控制台打印如下
21:52:10.966 [main] INFO com.thc.design.matter.EGM - EGM 写入数据 key: user_name1 , val : 周杰伦 21:52:10.968 [main] INFO com.thc.design.matter.EGM - EGM获取数据 key: user_name1 测试结果: 周杰伦 21:52:10.969 [main] INFO com.thc.design.matter.IIR - IIR写入数据 key:user_name2 val:周润发 21:52:10.969 [main] INFO com.thc.design.matter.IIR - IIR获取数据 key: user_name2 测试结果: 周润发
可以看到通过传递type 不同, 实现了走不同的缓存 .
使用抽象工厂模式的写法 定义适配接口ICacheAdapter
public interface ICacheAdapter {
String get(final String key);
void set(String key, String value);
void set(String key, String value, long timeout, TimeUnit timeUnit);
void del(String key);
}
创建不同集群缓存的实现
EGMCacheAdapter
import java.util.concurrent.TimeUnit;
/**
* 类名称:EGMCacheAdapter
* 类描述: egm 缓存适配器
* @author: https://javaweixin6.blog.csdn.net/
* 创建时间:2022/3/16 20:49
*/
public class EGMCacheAdapter implements ICacheAdapter {
private EGM egm = new EGM();
public String get(String key) {
return egm.gain(key);
}
public void set(String key, String value) {
egm.set(key, value);
}
public void set(String key, String value, long timeout, TimeUnit timeUnit) {
egm.setEx(key, value, timeout, timeUnit);
}
public void del(String key) {
egm.delete(key);
}
}
IIRCacheAdapter
public class IIRCacheAdapter implements ICacheAdapter {
private IIR iir = new IIR();
public String get(String key) {
return iir.get(key);
}
public void set(String key, String value) {
iir.set(key, value);
}
public void set(String key, String value, long timeout, TimeUnit timeUnit) {
iir.setExpire(key, value, timeout, timeUnit);
}
public void del(String key) {
iir.del(key);
}
}
创建代理类
public class JDKProxy {
// jdk动态代理 通过类加载器获取类
public static T getProxy(Class interfaceClass, ICacheAdapter cacheAdapter) {
InvocationHandler handler = new JDKInvocationHandler(cacheAdapter);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class[] classes = interfaceClass.getInterfaces();
return (T) Proxy.newProxyInstance(classLoader, new Class[]{classes[0]}, handler);
}
}
创建类加载器工具类
package com.thc.design.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class ClassLoaderUtils {
private static Set primitiveSet = new HashSet();
static {
primitiveSet.add(Integer.class);
primitiveSet.add(Long.class);
primitiveSet.add(Float.class);
primitiveSet.add(Byte.class);
primitiveSet.add(Short.class);
primitiveSet.add(Double.class);
primitiveSet.add(Character.class);
primitiveSet.add(Boolean.class);
}
/**
* 得到当前ClassLoader
*
* @return ClassLoader
*/
public static ClassLoader getCurrentClassLoader() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl == null) {
cl = ClassLoaderUtils.class.getClassLoader();
}
return cl == null ? ClassLoader.getSystemClassLoader() : cl;
}
/**
* 得到当前ClassLoader
*
* @param clazz 某个类
* @return ClassLoader
*/
public static ClassLoader getClassLoader(Class clazz) {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader != null) {
return loader;
}
if (clazz != null) {
loader = clazz.getClassLoader();
if (loader != null) {
return loader;
}
return clazz.getClassLoader();
}
return ClassLoader.getSystemClassLoader();
}
/**
* 根据类名加载Class
*
* @param className 类名
* @return Class
* @throws ClassNotFoundException 找不到类
*/
public static Class forName(String className)
throws ClassNotFoundException {
return forName(className, true);
}
/**
* 根据类名加载Class
*
* @param className 类名
* @param initialize 是否初始化
* @return Class
* @throws ClassNotFoundException 找不到类
*/
public static Class forName(String className, boolean initialize)
throws ClassNotFoundException {
return Class.forName(className, initialize, getCurrentClassLoader());
}
/**
* 根据类名加载Class
*
* @param className 类名
* @param cl Classloader
* @return Class
* @throws ClassNotFoundException 找不到类
*/
public static Class forName(String className, ClassLoader cl)
throws ClassNotFoundException {
return Class.forName(className, true, cl);
}
/**
* 实例化一个对象(只检测默认构造函数,其它不管)
*
* @param clazz 对象类
* @param 对象具体类
* @return 对象实例
* @throws Exception 没有找到方法,或者无法处理,或者初始化方法异常等
*/
public static T newInstance(Class clazz) throws Exception {
if (primitiveSet.contains(clazz)) {
return null;
}
if (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers())) {
Constructor constructorList[] = clazz.getDeclaredConstructors();
Constructor defaultConstructor = null;
for (Constructor con : constructorList) {
if (con.getParameterTypes().length == 1) {
defaultConstructor = con;
break;
}
}
if (defaultConstructor != null) {
if (defaultConstructor.isAccessible()) {
return (T) defaultConstructor.newInstance(new Object[]{null});
} else {
try {
defaultConstructor.setAccessible(true);
return (T) defaultConstructor.newInstance(new Object[]{null});
} finally {
defaultConstructor.setAccessible(false);
}
}
} else {
throw new Exception("The " + clazz.getCanonicalName() + " has no default constructor!");
}
}
try {
return clazz.newInstance();
} catch (Exception e) {
Constructor constructor = clazz.getDeclaredConstructor();
if (constructor.isAccessible()) {
throw new Exception("The " + clazz.getCanonicalName() + " has no default constructor!", e);
} else {
try {
constructor.setAccessible(true);
return constructor.newInstance();
} finally {
constructor.setAccessible(false);
}
}
}
}
public static Class[] getClazzByArgs(Object[] args) {
Class[] parameterTypes = new Class[args.length];
for (int i = 0; i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?