JAVA【设计模式】抽象工厂模式
一、定义
抽象工厂模式,类似于动态代理对象的生成工厂,集中管理各个代理对象,使用代理对象解决实际业务场景,减少代码的依赖
抽象⼯⼚模式与⼯⼚⽅法模式虽然主要意图都是为了解决,接⼝
选择问题。但在实现上,抽象⼯⼚是⼀个中⼼⼯⼚,创建其他⼯⼚
的模式
二、示例:
模拟场景:
很多时候初期业务的蛮荒发展,也会牵动着研发对系统的建设。
预估 QPS较低 、 系统压⼒较⼩ 、 并发访问不⼤ 、 近⼀年没有⼤动作 等等,在考虑时间投⼊成本的前提前,并不会投⼊特别多的⼈⼒去构建⾮常完善的系统。就像对 Redis 的使⽤,往往可能只要是单机
的就可以满⾜现状。
但随着业务超过预期的快速发展,系统的负载能⼒也要随着跟上。原有的单机 Redis 已经满⾜不了系
统需求。这时候就需要更换为更为健壮的Redis集群服务
,虽然需要修改但是不能影响⽬前系统的运
⾏,还要平滑过渡过去。
随着这次的升级,可以预⻅的问题会有;
- 很多服务⽤到了Redis需要⼀起升级到集群。
- 需要兼容集群A和集群B,便于后续的灾备。
- 两套集群提供的
接⼝和⽅法各有差异
,需要做适配
。 - 不能影响到⽬前正常运⾏的系统。
传统硬编码方式(都在一个类里面实现,多重if else嵌套使用)
定义集群接口:CacheClusterService
package com.qf.design.create.abstractfactory.tradition.cluster;
import java.util.concurrent.TimeUnit;
public interface CacheClusterService {
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);
}
集群接口实现:CacheClusterImpl
,随着集群类型变多,if else判断也变多,需要修改
以前的代码,违背了开闭原则
package com.qf.design.create.abstractfactory.tradition.cluster;
import com.qf.design.create.abstractfactory.tradition.redis.RedisUtils;
import com.qf.design.create.abstractfactory.tradition.redis.cluster.EGM;
import com.qf.design.create.abstractfactory.tradition.redis.cluster.IIR;
import java.util.concurrent.TimeUnit;
public class CacheClusterImpl implements CacheClusterService {
private RedisUtils redisUtils=new RedisUtils();
private EGM egm=new EGM();
private IIR iir=new IIR();
@Override
public String get(String key, int redisType) {
if (redisType==1){
return egm.gain(key);
}
if (redisType==2){
return iir.get(key);
}
return redisUtils.get(key);
}
@Override
public void set(String key, String value, int redisType) {
if (redisType==1){
egm.set(key,value);
}
if (redisType==2){
iir.set(key,value);
}
redisUtils.set(key,value);
}
@Override
public void set(String key, String value, long timeout, TimeUnit timeUnit, int redisType) {
if (redisType==1){
egm.setEx(key,value,timeout,timeUnit);
}
if (redisType==2){
iir.setExpire(key,value,timeout,timeUnit);
}
redisUtils.set(key,value,timeout,timeUnit);
}
@Override
public void del(String key, int redisType) {
if (redisType==1){
egm.delete(key);
}
if (redisType==2){
iir.del(key);
}
redisUtils.del(key);
}
}
测试:ApiTest
package com.qf.design.create.abstractfactory.tradition.cluster;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ApiTest {
private static Logger logger= LoggerFactory.getLogger(Logger.class);
public static void main(String[] args) {
CacheClusterImpl cacheCluster=new CacheClusterImpl();
cacheCluster.set("mykey","values01",1);
String mykey01 = cacheCluster.get("mykey", 1);
logger.info("EGM values:"+mykey01);
cacheCluster.set("mykey","values02",2);
String mykey02 = cacheCluster.get("mykey", 2);
logger.info("EGM values:"+mykey02);
}
}
抽象工厂模式
定义缓存实现接口:ICacheAdapter
package com.qf.design.create.abstractfactory.design.workshop;
import java.util.concurrent.TimeUnit;
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);
}
EGMCache缓存实现接口:EGMCacheAdapter
package com.qf.design.create.abstractfactory.design.workshop.impl;
import com.qf.design.create.abstractfactory.design.workshop.ICacheAdapter;
import com.qf.design.create.abstractfactory.tradition.redis.cluster.EGM;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
public class EGMCacheAdapter implements ICacheAdapter {
private EGM egm=new EGM();
@Override
public String get(String key) {
return egm.gain(key);
}
@Override
public void set(String key, String value) {
egm.set(key,value);
}
@Override
public void set(String key, String value, long timeout, TimeUnit timeUnit) {
egm.setEx(key,value,timeout,timeUnit);
}
@Override
public void del(String key) {
egm.delete(key);
}
}
IIRCache缓存实现接口:IIRCacheAdapter
package com.qf.design.create.abstractfactory.design.workshop.impl;
import com.qf.design.create.abstractfactory.design.workshop.ICacheAdapter;
import com.qf.design.create.abstractfactory.tradition.redis.cluster.IIR;
import java.util.concurrent.TimeUnit;
public class IIRCacheAdapter implements ICacheAdapter {
private IIR iir=new IIR();
@Override
public String get(String key) {
return iir.get(key);
}
@Override
public void set(String key, String value) {
iir.set(key,value);
}
@Override
public void set(String key, String value, long timeout, TimeUnit timeUnit) {
iir.setExpire(key,value,timeout,timeUnit);
}
@Override
public void del(String key) {
iir.del(key);
}
}
JDK动态代理:JDKInvocationHandler
package com.qf.design.create.abstractfactory.design.factory;
import com.qf.design.create.abstractfactory.design.workshop.ICacheAdapter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class JDKInvocationHandler implements InvocationHandler {
private ICacheAdapter iCacheAdapter;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(iCacheAdapter,args);
}
public void bind(Object obj) {
this.iCacheAdapter= (ICacheAdapter) obj;
}
}
JDK动态代理的实现工厂:JDKProxyFactory
package com.qf.design.create.abstractfactory.design.factory;
import java.lang.reflect.Proxy;
public class JDKProxyFactory {
public static Object getProxyInstance(Object obj){ //被代理的对象
JDKInvocationHandler myInvocationHandler=new JDKInvocationHandler();
myInvocationHandler.bind(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),myInvocationHandler);
}
}
测试:ApiTest
package com.qf.design.create.abstractfactory.design.factory;
import com.qf.design.create.abstractfactory.design.workshop.ICacheAdapter;
import com.qf.design.create.abstractfactory.design.workshop.impl.EGMCacheAdapter;
import com.qf.design.create.abstractfactory.design.workshop.impl.IIRCacheAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ApiTest {
private static Logger logger= LoggerFactory.getLogger(Logger.class);
public static void main(String[] args) {
ICacheAdapter proxyInstance01 = (ICacheAdapter) JDKProxyFactory.getProxyInstance(new IIRCacheAdapter());
proxyInstance01.set("mykey","values01");
String mykey01 = proxyInstance01.get("mykey");
logger.info("IIR values:"+mykey01);
ICacheAdapter proxyInstance02 = (ICacheAdapter) JDKProxyFactory.getProxyInstance(new EGMCacheAdapter());
proxyInstance02.set("mykey","values02");
String mykey02 = proxyInstance02.get("mykey");
logger.info("EGM values:"+mykey02);
}
}
UML关系图
未使用抽象工厂模式
每新增一个实现,需要重新进行if else判断,修改之前的代码逻辑
抽象工厂模式:都共同实现接口ICacheAdapter
,以便于jdk动态代理对象获取每个代理对象
总结:
这个设计模式满⾜了;单⼀职责
、开闭原则
、解耦
等优点,但如果说随着业务的不断拓展,可能会造成类实现上的复杂度。但也可以说算不上缺点,因为可以随着其他设计⽅式的引⼊和代理类以及⾃动⽣成加载的⽅式降低此项缺点。