面向对象编程中使用统一类存储程序核心运行对象是否可行?
面向对象编程组件管理设计问题
这是我在面向对象编程(Object-Oriented Programming)中遇到的一个设计问题,我一直在寻找最优解决方案,但目前想到的方案我都不太确定是否适用。
问题说明
我编写了一个名为ComponentsHub的类,设计思路是在其中存储程序运行所需的所有核心对象,每个对象都用static、final、public修饰,使用public访问修饰符是为了可以通过静态导入或者直接静态访问的方式便捷调用对象。
package com.rtransfer.net.components; import java.io.IOException; import java.util.logging.FileHandler; import java.util.logging.Logger; import com.rtransfer.net.system.StorageManager; public class ComponentsHub { public static final Logger logger; public static final Server server; public static final StorageManager storageManager; public static final SecurityManager securityManager; public static final RequestForwarder requestForwarder; public static final Authenticator authenticator; public static final Uploader uploader; public static final ConnectionHandler connectionHandler; public static final Listener listener; static { logger = Logger.getLogger("rtransfer.net"); try { FileHandler handler = new FileHandler("logs/logs.txt"); logger.addHandler(handler); } catch (SecurityException | IOException e) { e.printStackTrace(); } server = new Server(); storageManager = new StorageManager(); securityManager = new SecurityManager(); requestForwarder = new RequestForwarder(); authenticator = new Authenticator(); uploader = new Uploader(); connectionHandler = new ConnectionHandler(); listener = new Listener(); } }
很明显这段代码/设计存在不少问题(也希望各位能指出相关问题),比如没有做关注点分离、难以测试、可扩展性差等,我对这个架构很不满意,感觉自己写出了一种“上帝类(God Class)”。
初步想到的解决方案
- 创建Builder或Factory等类来生成这些对象,将对象构造和初始化的职责从ComponentsHub中剥离。
- 按类别对这些对象做聚合,也就是拆分出多个子ComponentsHub类。
我知道这是面向对象系统设计中非常常见的一类问题,我希望能解决这个问题,避免后续软件维护开发出现严重问题。我想到的这两个方案能不能解决部分问题?有没有其他替代方案?也希望大家能给我推荐合适的设计模式或者其他技术方案来解决这个问题,我应该在什么地方、以什么方式创建对象,同时还能保证访问的便捷性?
方案迭代反馈结果
根据评论区的一条建议,我实现了服务定位器(ServiceLocator)模式,看起来比之前的方案好很多。我知道目前业界对ServiceLocator是不是反模式存在争议,我也了解它的缺点,但如果没有相关框架支持,使用传统的依赖注入会非常繁琐(也有回答提到了这一点)。
public class InitialContext { public ServiceComponent lookup(String serviceName) { if (serviceName.equalsIgnoreCase(Listener.class.getSimpleName())) { return new Listener(); } else if (serviceName.equalsIgnoreCase(ConnectionHandler.class.getSimpleName())) { return new ConnectionHandler(); } else if (serviceName.equalsIgnoreCase(Uploader.class.getSimpleName())) { return new Uploader(); } else if (serviceName.equalsIgnoreCase(Authenticator.class.getSimpleName())) { return new Authenticator(); } else if (serviceName.equalsIgnoreCase(RequestForwarder.class.getSimpleName())) { return new RequestForwarder(); } else if (serviceName.equalsIgnoreCase(SecurityManager.class.getSimpleName())) { return new SecurityManager(); } else if (serviceName.equalsIgnoreCase(StorageManager.class.getSimpleName())) { return new StorageManager(); } else if (serviceName.equalsIgnoreCase(Server.class.getSimpleName())) { return new Server(); } else { return null; } } }
public class ServiceCache { private Hashtable<String, ServiceComponent> services; public ServiceCache() { services = new Hashtable<>(); } public ServiceComponent getService(Class<?> service) { return services.get(service.getSimpleName()); } public void addService(ServiceComponent newService) { services.put(newService.getClass().getSimpleName(), newService); } }
package com.rtransfer.net.components; import com.rtransfer.utils.InitialContext; import com.rtransfer.utils.ServiceCache; public class ServiceLocator { private static ServiceCache cache = new ServiceCache(); public static ServiceComponent getService(Class<?> serviceClass) { ServiceComponent service = cache.getService(serviceClass); if (service != null) return service; InitialContext context = new InitialContext(); service = context.lookup(serviceClass.getSimpleName()); cache.addService(service); return service; } }
最终选型
最终我决定采用*依赖注入(dependency injection)*方案。
内容的提问来源于stack exchange,提问作者InSaNiTy
相关产品推荐
相关产品推荐

