如何遵循开闭原则优化WoW角色创建工厂类?
解决UpdateAvatarFactory违反开闭原则的方案
当前UpdateAvatarFactory的核心问题是硬编码了所有角色创建类的实例化逻辑,新增角色必须修改构造方法,完全违背了开闭原则。下面提供几种可落地的解决思路:
方案一:反射+配置文件动态加载
思路
将角色创建类的全限定类名与角色名的映射关系配置到外部文件(如avatar-config.properties),工厂类启动时读取配置,通过反射动态实例化对象并添加到avatarFactory。新增角色只需修改配置文件,无需改动工厂代码。
配置文件示例(avatar-config.properties)
Human=com.example.CreateHuman Elf=com.example.CreateElf Gnome=com.example.CreateGnome Orc=com.example.CreateOrc # 新增Tauren只需添加这一行 Tauren=com.example.CreateTauren
修改后的UpdateAvatarFactory代码
import java.io.IOException; import java.util.Properties; public class UpdateAvatarFactory { public UpdateAvatarFactory(Client client) { Properties config = new Properties(); try { // 加载配置文件 config.load(UpdateAvatarFactory.class.getClassLoader().getResourceAsStream("avatar-config.properties")); for (String roleName : config.stringPropertyNames()) { String className = config.getProperty(roleName); // 反射实例化角色创建类 ICreateMethod createMethod = (ICreateMethod) Class.forName(className).newInstance(); createMethod.name = roleName; client.avatarFactory.addCreateMethod(createMethod); } } catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) { e.printStackTrace(); // 实际项目中建议做更合理的异常处理 } } }
方案二:依赖注入(DI)
思路
将所有ICreateMethod的实现类实例通过构造方法注入,工厂类不再负责实例化逻辑。纯Java环境下可通过构造方法传入集合;如果用Spring等DI框架,只需将新的角色创建类标记为@Component,框架会自动收集并注入。
修改后的UpdateAvatarFactory代码(纯Java版)
import java.util.List; public class UpdateAvatarFactory { // 通过构造方法注入所有角色创建类实例 public UpdateAvatarFactory(Client client, List<ICreateMethod> createMethods) { for (ICreateMethod method : createMethods) { client.avatarFactory.addCreateMethod(method); } } }
使用示例(外部组装)
// 新增Tauren只需添加到集合中,无需修改工厂类 List<ICreateMethod> methods = List.of( new CreateHuman(), new CreateElf(), new CreateGnome(), new CreateOrc(), new CreateTauren() ); UpdateAvatarFactory factory = new UpdateAvatarFactory(client, methods);
方案三:静态注册机制
思路
让每个ICreateMethod的实现类在静态代码块中自行注册到全局注册中心,工厂类只需将注册中心的内容同步到client的avatarFactory。新增角色时,只需编写新的实现类,无需修改任何现有工厂代码。
注册中心示例
import java.util.ArrayList; import java.util.List; public class CreateMethodRegistry { private static final List<ICreateMethod> REGISTRY = new ArrayList<>(); public static void register(ICreateMethod method) { REGISTRY.add(method); } public static List<ICreateMethod> getRegisteredMethods() { return new ArrayList<>(REGISTRY); } }
角色创建类示例(以CreateTauren为例)
public class CreateTauren implements ICreateMethod { static { CreateTauren taurenCreator = new CreateTauren(); taurenCreator.name = "Tauren"; CreateMethodRegistry.register(taurenCreator); } // 实现ICreateMethod的其他方法 }
修改后的UpdateAvatarFactory代码
public class UpdateAvatarFactory { public UpdateAvatarFactory(Client client) { List<ICreateMethod> createMethods = CreateMethodRegistry.getRegisteredMethods(); for (ICreateMethod method : createMethods) { client.avatarFactory.addCreateMethod(method); } } }
内容的提问来源于stack exchange,提问作者Z.J
相关产品推荐
相关产品推荐

