通过反射实现策略模式
我正在尝试使用反射来实现 策略模式,即使用它实例化一个新的具体策略对象类名。
我想要一个包含类名的可配置文件。我们有一个数据库管理器,可以在运行时进行更改。这是我到目前为止所拥有的:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您确定没有忘记包名称并且类 ConcreteStrategy 可用于类加载器吗?
Are you sure you don't forget package name and class ConcreteStrategy is available for classloader?
假设您提供给 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 ofConcreteStrategy.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 orjar_with_ConcreteStrategy_class.jar
.URLClassLoader example.