通过反射实现策略模式

发布于 2024-12-06 02:29:38 字数 1143 浏览 1 评论 0原文

我正在尝试使用反射来实现 策略模式,即使用它实例化一个新的具体策略对象类名。

我想要一个包含类名的可配置文件。我们有一个数据库管理器,可以在运行时进行更改。这是我到目前为止所拥有的:

StrategyInterface intrf = null;
try {
    String className = (String)table.get(someId);
    intrf = (StrategyInterface) Class.forName(className).newInstance();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    System.out.println(e.getMessage());
}
return intrf;

我有一个实现 StrategyInterface 的类 ConcreteStrategy。我在 whcih table.get(someID) 返回 String "ConcreteStrategy" 中运行测试。

我的问题是抛出了 ClassNotFoundEception 。为什么会发生这种情况,以及如何在给定类名的情况下实例化 ConcreteStrategy ?我不想使用 if-else 块,因为具体策略对象的数量会随着时间和开发而增加。

编辑:我按以下方式修复了它,

String className = (String)table.get(custId);
className = TrackingLimiter.class.getPackage().getName() + "." + className;
limiter = (TrackingLimiter) Class.forName(className).newInstance();

I'm trying to implement the strategy pattern using reflection, i.e. instantiate a new Concrete Strategy object using it's class name.

I want to have a configurable file with the class name in it. We have a database manager that will make changes available during run-time. Here's what I have so far:

StrategyInterface intrf = null;
try {
    String className = (String)table.get(someId);
    intrf = (StrategyInterface) Class.forName(className).newInstance();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    System.out.println(e.getMessage());
}
return intrf;

I have a Class ConcreteStrategy which implements StrategyInterface. I have a test running in whcih table.get(someID) returns the String "ConcreteStrategy".

My problem is that ClassNotFoundEception is thrown. Why is this happening, and how I could get ConcreteStrategy to be instantiated given a class name? I don't want to use an if-else block because number of concrete strategy objects will increase with time and development.

EDIT: I fixed it the following way,

String className = (String)table.get(custId);
className = TrackingLimiter.class.getPackage().getName() + "." + className;
limiter = (TrackingLimiter) Class.forName(className).newInstance();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

明媚殇 2024-12-13 02:29:38

您确定没有忘记包名称并且类 ConcreteStrategy 可用于类加载器吗?

Are you sure you don't forget package name and class ConcreteStrategy is available for classloader?

关于从前 2024-12-13 02:29:38

假设您提供给 forName() 的类名是完全限定且正确的。

ClassNotFoundException 正是这个意思。

因此,您需要确保 ConcreteStrategy.class(或包含它的 jar 文件)位于类路径中。

如果新的类真正动态地可用,即您知道当您的程序启动时,ConcreteStrategy.class 不存在,但几个小时/几天后有人实现了它并放置了完全限定的类名在数据库表中,除了类名之外,您还需要资源名称(ConcreteStrategy.class 的路径(或包含它的 jar 文件))。

一旦两者都具备,您就可以使用 URLClassLoader 从 ConcreteStrategy.class 文件或 jar_with_ConcreteStrategy_class.jar 创建 ConcreteStrategy 实例。

URLClassLoader 示例。

Assuming that classname you provide to forName() is fully qualified and correct.

ClassNotFoundException means exactly that.

So you need to ensure that the ConcreteStrategy.class (or a jar file containing it) is in class path.

In case new classes are made available really dynamically, i.e. you know that when YOUR program started, ConcreteStrategy.class did not exist, but a few hours/days later someone implemented it and put the fully qualified class name in the DB table, then along with the class name you also need the resource name (path of ConcreteStrategy.class (or a jar file containing it)).

Once you have both, you can use URLClassLoader to create an instance of ConcreteStrategy from ConcreteStrategy.class file or jar_with_ConcreteStrategy_class.jar.

URLClassLoader example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文