Java石头剪刀布游戏:如何用字符串调用对应策略类?
如何在Java中根据字符串实例化策略类
嘿,这个需求在策略模式的实践里太常见了!我给你两种靠谱的实现方式,你可以根据项目的复杂度和需求来选:
方法一:使用反射机制(快速实现)
如果只是快速验证需求,反射是最直接的方式——直接通过类名字符串来加载并实例化对象。假设你的策略接口叫Strategy,所有策略类(比如RockStrat、PaperStrat)都实现了这个接口,代码可以这么写:
import java.util.Scanner; public class GameLauncher { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入策略名称(如PaperStrat):"); String stratName = scanner.nextLine(); // 注意:如果策略类在某个包下,要加上完整包名,比如 "com.yourpackage.PaperStrat" String fullClassName = stratName; try { // 加载类并实例化 Class<?> stratClass = Class.forName(fullClassName); Strategy strategy = (Strategy) stratClass.getDeclaredConstructor().newInstance(); // 调用策略的方法,比如假设接口有play()方法 strategy.play(); } catch (ClassNotFoundException e) { System.out.println("找不到对应的策略类:" + stratName); } catch (Exception e) { System.out.println("实例化策略类出错:" + e.getMessage()); } } }
注意点:
- 一定要确保输入的字符串和类名完全一致(大小写敏感),如果类在特定包下,必须加上完整的包路径;
- 反射会抛出多种检查异常,必须做好异常处理;
- 如果策略类没有无参构造函数,需要修改代码,调用对应的带参构造方法。
方法二:使用工厂模式(推荐,更安全可控)
反射虽然快,但存在性能开销、类型不安全、依赖类名硬编码等问题。如果是正式项目,更推荐用策略工厂来封装实例化逻辑,代码更清晰也更易维护:
首先定义策略接口:
public interface Strategy { void play(); }
然后实现具体策略类:
public class RockStrat implements Strategy { @Override public void play() { System.out.println("出石头!"); } } public class PaperStrat implements Strategy { @Override public void play() { System.out.println("出布!"); } }
接下来创建策略工厂:
import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; public class StrategyFactory { // 用Map存储策略名称到实例供应商的映射 private static final Map<String, Supplier<Strategy>> STRATEGY_MAP = new HashMap<>(); // 静态初始化块,注册所有策略 static { STRATEGY_MAP.put("RockStrat", RockStrat::new); STRATEGY_MAP.put("PaperStrat", PaperStrat::new); // 后续加新策略,只需要在这里添加一行即可 } // 根据名称获取策略实例 public static Strategy getStrategy(String stratName) { Supplier<Strategy> supplier = STRATEGY_MAP.get(stratName); if (supplier == null) { throw new IllegalArgumentException("不存在的策略:" + stratName); } return supplier.get(); } }
最后在游戏中调用工厂:
import java.util.Scanner; public class GameLauncher { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入策略名称(如PaperStrat):"); String stratName = scanner.nextLine(); try { Strategy strategy = StrategyFactory.getStrategy(stratName); strategy.play(); } catch (IllegalArgumentException e) { System.out.println(e.getMessage()); } } }
优势:
- 完全避免了反射的弊端,类型安全,性能更好;
- 策略的注册和管理集中在工厂类,后续新增策略只需要修改工厂的静态块,符合开闭原则;
- 异常处理更简洁,直接判断策略是否存在即可。
如果你的策略类很多,不想手动注册,也可以结合反射来自动扫描并加载策略类(比如扫描特定包下的所有Strategy实现类),不过这就属于进阶玩法了,基础场景下上面的工厂模式完全够用~
内容的提问来源于stack exchange,提问作者Rémy.W
相关产品推荐
相关产品推荐

