在新课程中我需要什么类型的过程来“阅读”下面这个课程中的所有颜色?我使用该类为组件设置颜色并喜欢它。但是现在是时候让我的应用程序右键单击面板并更改背景颜色了。
在继续使用这些颜色时,是什么让我在正确的方向上开始编码:ColorFactory.java
我刚刚开始考虑向类添加一个新方法,例如:
public Map<String, Color> getColorMapValues(){
return colorMap;
//
}
在新课程中我需要什么类型的过程来“阅读”下面这个课程中的所有颜色?我使用该类为组件设置颜色并喜欢它。但是现在是时候让我的应用程序右键单击面板并更改背景颜色了。
在继续使用这些颜色时,是什么让我在正确的方向上开始编码:ColorFactory.java
我刚刚开始考虑向类添加一个新方法,例如:
public Map<String, Color> getColorMapValues(){
return colorMap;
//
}
您可以通过反射访问颜色图。我不保证以下代码,因为我手头没有 IDE,但这应该可以解决问题:
private static Map<String, Color> getColorMap() throws Exception {
Field colorMapField = ColorFactory.class.getDeclaredField("colorMap");
colorMapField.setAccessible(true);
return (Map<String, Color>) colorMapField.get(ColorFactory.getInstance());
}
然后您可以查询返回的颜色图以按名称获取颜色:
Map<String, Color> colorMap = getColorMap();
Color yellow = colorMap.get("yellow");
如果你想修改颜色图,只需用上面的方法检索它,put()“任何你喜欢的颜色”(是的,Pink Floyd 参考!),然后调用这个方法:
public void setColorMap(Map<String, Color> colorMap) throws Exception {
Field colorMapField = ColorFactory.class.getDeclaredField("colorMap");
colorMapField.setAccessible(true);
colorMapField.set(ColorFactory.getInstance(), colorMap);
}
请注意,这对于类的同步策略是非常危险的,但如果您不使用多个线程发送垃圾邮件,它应该可以工作。
由于在这种情况下您可以控制源代码,因此最好重构类以满足您的需求而不是使用反射(这不仅昂贵,而且根据您的安全策略被禁止)。
常用的技术是Holder pattern
. 有关更多信息,请参阅 Joshua Bloch 的 Effective Java(第 2 版)第 71 条。我们还可以通过使用线程安全的非阻塞结构来避免读取同步,即java.util.concurrent.ConcurrentHashMap
.
public class ColorFactory {
private static class ColorFactoryHolder {
// creates on instantiation of ColorFactoryHolder
// synchronization is baked into the JVM, but won't be created until
// the class is used, see JLS 12.4.1
static final ColorFactory instance = new ColorMap();
}
public static ColorFactory getInstance() { return ColorFactoryHolder.instance; }
// concurrent hash map - all operations are thread safe
Map<String,Color> colormap = new ConcurrentHashMap<String,Color>();
private final Object lock = new Object();
private ColorFactory() {
colormap.add("blue",new Color(0,0,255));
// rest of colors here
}
public Color getColor(String spec) {
if(colormap.containsKey(spec)) return colormap.get(spec);
// don't synchronize externally - Bloch et al, item 70
synchronized(lock) {
// double check idiom - not broken, as map is thread safe
if(colormap.containsKey(spec)) return colormap.get(spec);
Color color = parse(spec); // parse method can be extracted from old code
colormap.put(spec,color);
return color;
}
}
private static Color parse(String spec) {
// parse the color spec here
}
}
事实上,因为解析操作可能非常非常快(与同步相比),我们可以完全取消同步。所以我们最终可能会多次解析这个值——这并不是一个大问题,因为每次结果都是一样的。见布洛赫等人。项目 69 了解更多信息。
public class ColorFactory {
private static class ColorFactoryHolder {
// same as above, snipped for brevity
}
public static ColorFactory getInstance() { return ColorFactoryHolder.instance; }
// requires ConcurrentMap reference to get putIfAbsent(K,V) method
ConcurrentMap<String,Color> colormap = new ConcurrentHashMap<String,Color>();
// private final Object lock = new Object(); - removed
private ColorFactory() {
colormap.add("blue",new Color(0,0,255));
// rest of colors here
}
public Color getColor(String spec) {
Color result = colormap.get(spec);
if(result == null) {
result = parse(spec); // may parse multiple times, but still
// cheaper than synchronization
colormap.putIfAbsent(spec,result);
}
return result
}
private static Color parse(String spec) {
// parse the color spec here
}
}