objectfactory.html
来自「基于mondrian 开源框架进行OLAP多维分析」· HTML 代码 · 共 888 行 · 第 1/3 页
HTML
888 行
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><!--NewPage--><HTML><HEAD><!-- Generated by javadoc (build 1.5.0_15) on Thu Jul 31 17:20:17 EDT 2008 --><TITLE>ObjectFactory (Mondrian OLAP Server, version 3.0.4.11371)</TITLE><META NAME="keywords" CONTENT="mondrian.util.ObjectFactory class"><LINK REL ="stylesheet" TYPE="text/css" HREF="../../stylesheet.css" TITLE="Style"><SCRIPT type="text/javascript">function windowTitle(){ parent.document.title="ObjectFactory (Mondrian OLAP Server, version 3.0.4.11371)";}</SCRIPT><NOSCRIPT></NOSCRIPT></HEAD><BODY BGCOLOR="white" onload="windowTitle();"><!-- ========= START OF TOP NAVBAR ======= --><A NAME="navbar_top"><!-- --></A><A HREF="#skip-navbar_top" title="Skip navigation links"></A><TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY=""><TR><TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1"><A NAME="navbar_top_firstrow"><!-- --></A><TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY=""> <TR ALIGN="center" VALIGN="top"> <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD> <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A> </TD> <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT> </TD> <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A> </TD> <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A> </TD> <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD> <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A> </TD> </TR></TABLE></TD><TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM></EM></TD></TR><TR><TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2"> <A HREF="../../mondrian/util/NotificationMemoryMonitor.html" title="class in mondrian.util"><B>PREV CLASS</B></A> <A HREF="../../mondrian/util/ObjectFactory.Context.html" title="interface in mondrian.util"><B>NEXT CLASS</B></A></FONT></TD><TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2"> <A HREF="../../index.html?mondrian/util/ObjectFactory.html" target="_top"><B>FRAMES</B></A> <A HREF="ObjectFactory.html" target="_top"><B>NO FRAMES</B></A> <SCRIPT type="text/javascript"> <!-- if(window==top) { document.writeln('<A HREF="../../allclasses-noframe.html"><B>All Classes</B></A>'); } //--></SCRIPT><NOSCRIPT> <A HREF="../../allclasses-noframe.html"><B>All Classes</B></A></NOSCRIPT></FONT></TD></TR><TR><TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2"> SUMMARY: <A HREF="#nested_class_summary">NESTED</A> | FIELD | <A HREF="#constructor_summary">CONSTR</A> | <A HREF="#method_summary">METHOD</A></FONT></TD><TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">DETAIL: FIELD | <A HREF="#constructor_detail">CONSTR</A> | <A HREF="#method_detail">METHOD</A></FONT></TD></TR></TABLE><A NAME="skip-navbar_top"></A><!-- ========= END OF TOP NAVBAR ========= --><HR><!-- ======== START OF CLASS DATA ======== --><H2><FONT SIZE="-1">mondrian.util</FONT><BR>Class ObjectFactory<V></H2><PRE><A HREF="http://java.sun.com/javase/6/docs/api/java/lang/Object.html" title="class or interface in java.lang">java.lang.Object</A> <IMG SRC="../../resources/inherit.gif" ALT="extended by "><B>mondrian.util.ObjectFactory<V></B></PRE><DL><DT><B>Direct Known Subclasses:</B> <DD><A HREF="../../mondrian/calc/ExpCompiler.Factory.html" title="class in mondrian.calc">ExpCompiler.Factory</A>, <A HREF="../../mondrian/util/ObjectFactory.Singleton.html" title="class in mondrian.util">ObjectFactory.Singleton</A></DD></DL><HR><DL><DT><PRE>public abstract class <B>ObjectFactory<V></B><DT>extends <A HREF="http://java.sun.com/javase/6/docs/api/java/lang/Object.html" title="class or interface in java.lang">Object</A></DL></PRE><P>Concrete derived classes of the generic <code>ObjectFactory</code> class are used to produce an implementation of an interface (a normal interface implementation or a Proxy). In general, a factory should produce a default implementation for general application use as well as particular implementations used during testing. During testing of application code and during normal execution, the application code uses one of the <code>ObjectFactory</code>'s methods for producing implementation instances - the same method is used both for test and non-test modes. There are two ways of modifying the implementation returned to the application code. The first is for the application to use Properties. The <code>ObjectFactory</code> implementation looks for a given property (by default the name of the property is the class name of the interfaceClass object) and if found uses it as the classname to create. A second approach is to use a ThreadLocal; if the ThreadLocal is non-empty then use it as the classname. <p> When to use a Factory? <p> Everyone has an opinion. For me, there are two criteria: enabling unit testing and providing end-user/developer-customizer overriding. <p> If a method has side-effects, either its result depends upon a side-effect or calling it causes a side-effect, then the Object hosting the method is a candidate for having a factory. Why? Well, consider the case where a method returns the value of a System property and the System property is determined only once and set to a static final variable: <pre> class OneValue { private static final boolean propValue; static { propValue = Boolean.getBoolean("com.app.info.value"); } ..... public boolean hasInfo() { return propValue; } } </pre> <p> In this case, only one value is ever returned. If you have a module, a client of the above code, that uses the value returned by a call to the <code>hasInfo()</code> method, how do you write a unit test of your module that tests both possible return values? You can not, its value is based upon a side-effect, an external value that can not be controled by the unit test. If the <code>OneValue</code> class was an interface and there was a factory, then the unit test could arrange that its own version of the <code>OneValue</code> interface was returned and in one test arrange that <code>true</code> was returned and in a second test, arrange that <code>false</code> was returned. <p> The above is a trivial example of code that disallows clients of the code from being properly tested. <p> Another example might be a module that directly initializes a JMS queue and receives JMS message from the JMS queue. This code can not be tested without having a live JMS queue. On the other hand, if one defines an interface allowing one to wrap access to the JMS queue and accesses the implementation via a factory, then unit tests can be create that use a mock JMS queue. <p> With regards to providing end-user/developer-customizer overriding, its generally good to have a flexible application framework. Experimental or just different implementations can be developed and tested without having to touch a lot of the application code itself. <p> There is, of course, a trade-off between the use of a factory and the size or simplicity of the object being created. <p> What are the requirements for a template ObjectFactory? <p> First, every implementation must support the writing of unit tests. What this means it that test cases can override what the factory produces. The test cases can all use the same produced Object or each can request an Object targeted to its particular test. All this without changing the <code>default</code> behavior of the factory. <p> Next, it should be possible to create a factory from the template that is intended to deliver the same Object each time it is called, a different, new Object each time it is called, or, based on the calling environment (parameters, properties, <code>ThreadLocal</code>, etc.) one of a set of Objects. These are possible <code>default</code> behaviors, but, again, they can be overridden for test purposes. <p> While a factory has a <code>default</code> behavior in an application, it must be possible for every factory's behavior in that application to be globally overridden. What that means is if the application designer has dictated a <code>default</code>, the application user should be able to change the default. An example of this is overriding what Object is returned based upon a <code>System</code> property value. <p> Lastly, every factory is a singleton - if an interface with an implementation whose creation is mediated by a factory, then there is a single factory that does that creating. This does not mean that such a factory always return the same value, rather that there is only one instance of the factory itself. <p> The following is an example class that generates a factory singleton. In this case, the factory extends the <code>ObjectFactory</code> rather than the <code>ObjectFactory.Singleton</code>: <pre> public final class FooFactory extends ObjectFactory<Foo> { // The single instance of the factory private static final FooFactory factory; static { factory = new FooFactory(); } public static FooFactory instance() { return factory; } .......... private FooFactory() { super(Foo.class); } .......... } </pre> <p> There are multiple ways of creating derived classes that have support for unit testing. A very simple way is to use <code>ThreadLocal</code>s. <pre> private static final ThreadLocal ClassName = new ThreadLocal(); private static String getThreadLocalClassName() { return (String) ClassName.get(); } public static void setThreadLocalClassName(String className) { ClassName.set(className); } public static void clearThreadLocalClassName() { ClassName.set(null); } .......... protected String getClassName() { return getThreadLocalClassName(); } </pre> <p> Here, the unit test will call the <code>setThreadLocalClassName</code> method setting it with the class name of a specialized implemetation of the template interface. In the <code>finally</code> clause of the unit test, it is very important that there be a call to the <code>clearThreadLocalClassName</code> method so that other tests, etc. do not get an instance of the test-specific specialized implementation. <p> The following is an example unit test that uses the factory's <code>ThreadLocal</code> to override the implementation that is returned. <pre> interface Boo { boolean getValue(); ....... } class NormalBooImpl implements Boo { public boolean getValue() { ... } ....... } class MyCode { private Boo boo; MyCode() { boo = BooFactory.instance().getObject(); } ....... int getValue() { if (boo.getValue()) { return 1; } else { return 0; } } } class MyCodeTest { private static boolean testValue; static class BooTest1 implements Boo { public boolean getValue() { return MyTest.testValue; } ..... }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?