Consider providing static factory methods instead of
constructors 考慮以靜態(tài)工廠方法取代構(gòu)造函數(shù)
The normal way for a class to allow a client to obtain an instance is to provide a public
constructor.
A class can provide a public static factory method, which is simply
a static method that returns an instance of the class
such as
public static Boolean valueOf(boolean b) {
return (b ? Boolean.TRUE : Boolean.FALSE);
}
advantages
1:One advantage of static factory methods is that, unlike constructors, they have names.
一個(gè)類靜態(tài)工廠方法是有名字的.If the parameters to a constructor do not, in and of themselves, describe the object being returned, a static factory with a well-chosen name can make a class easier to use and the resulting client code easier to read. 如BigInteger(int, int,Random)只知道new了一個(gè)BigInteger對(duì)象,而BigInteger.probablePrime()能說明返回的可能是一個(gè)素?cái)?shù)對(duì)象.另外,如果一個(gè)構(gòu)造函數(shù)僅僅由于參數(shù)順序不同而意思也不同.靜態(tài)工廠方法就更加有用了.它更能說明函數(shù)的意思.因?yàn)樗幸粋€(gè)名字.
the reason?are : If the parameters to a constructor do not, describe the object being
returned, a static factory with a well-chosen name can make a class easier to use and the
resulting client code easier to read.
2:A second advantage of static factory methods is that, unlike constructors, they are not
required to create a new object each time they're invoked.每次請(qǐng)求時(shí),不需要重新創(chuàng)建一個(gè)對(duì)象----單例的意思.這可以在任何時(shí)刻控制這個(gè)對(duì)象,同時(shí)在比較的時(shí)候也不需要用equals而用= =就可以解決了.
3:A third advantage of static factory methods is that, unlike constructors, they can return
an object of any subtype of their return type.可以返回一個(gè)原返回類型的子類型對(duì)象.
One application of this flexibility is that an API can return objects without making their
classes public.Hiding implementation classes in this fashion can lead to a very compact API.這種靈活性的一個(gè)應(yīng)用是,一個(gè)A P I可以返回一個(gè)對(duì)象,同時(shí)又不使該對(duì)象的類成為公有的。以這種方式把具體的實(shí)現(xiàn)類隱藏起來,可以得到一個(gè)非常簡(jiǎn)潔的A P I。這項(xiàng)技術(shù)非常適合
于基于接口的框架結(jié)構(gòu),因?yàn)樵谶@樣的框架結(jié)構(gòu)中,接口成為靜態(tài)工廠方法的自然返回類型
sample:
// Provider framework sketch
public abstract class Foo {
// Maps String key to corresponding Class object
private static Map implementations = null;
// Initializes implementations map the first time it's called
private static synchronized void initMapIfNecessary() {
if (implementations == null) {
implementations = new HashMap();
// Load implementation class names and keys from
// Properties file, translate names into Class
// objects using Class.forName and store mappings.
...
}
}
public static Foo getInstance(String key) {
initMapIfNecessary();
Class c = (Class) implementations.get(key);
if (c == null)
return new DefaultFoo();
try {
return (Foo) c.newInstance();
} catch (Exception e) {
return new DefaultFoo();
}
}
}
公有的靜態(tài)工廠方法所返回的對(duì)象的類不僅可以是非公有的,而且該類可以隨著每次調(diào)用
而發(fā)生變化,這取決于靜態(tài)工廠方法的參數(shù)值。只要是已聲明的返回類型的子類型,都是允
許的。而且,為了增強(qiáng)軟件的可維護(hù)性,返回對(duì)象的類也可以隨著不同的發(fā)行版本而不同。
disadvantages:
1:The main disadvantage of static factory methods is that classes without public or protected constructors cannot be subclassed.
類如果不含公有的或者受保護(hù)的構(gòu)造函數(shù),就不能被子類化。對(duì)于公有的靜態(tài)工廠所返回的非公有類,也同樣如此
2:A second disadvantage of static factory methods is that they are not readily distinguishable from other static methods.
In summary, static factory methods and public constructors both have their uses, and it pays to understand their relative merits. Avoid the reflex to provide constructors without first considering static factories because static factories are often more appropriate. If you've weighed the two options and nothing pushes you strongly in either direction, it's probably best to provide a constructor simply because it's the norm.
接口修改為
package net.blogjava.dodoma.spring.aop;
public interface HelloI {
?public String sayHello(String firstName,String lastName)throws Exception;
?}
類修改為
package net.blogjava.dodoma.spring.aop;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Hello implements HelloI {
?protected static final Log log=LogFactory.getLog(Hello.class);
?private String msg;
?public Hello(){}
?public Hello(String msg){
??this.msg=msg;
?}
?
?public String getMsg() {
??return msg;
?}
?public void setMsg(String msg) {
??this.msg = msg;
?}
?public String sayHello(String firstName, String lastName) throws Exception{
??// TODO Auto-generated method stub
??log.info("in the class "+this.getClass().getName()+"'s method sayHello()");
? throw new Exception("here is a exception !");
??return (msg+" "+firstName+" "+lastName);
?}
}
package net.blogjava.dodoma.spring.aop;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.ThrowsAdvice;
public class LogThrowAdvice implements ThrowsAdvice {
?protected static final Log log = LogFactory.getLog(LogThrowAdvice.class);
?public void afterThrowing(Exception e)throws Throwable{
??log.info("in the class "+this.getClass().getName()+"'s method afterThrowing()");
??log.info("the exception is "+e.getMessage());
?}
}
package net.blogjava.dodoma.spring.aop;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
public class HelloTest {
?protected static final Log log = LogFactory.getLog(HelloTest.class);
?/**
? * @param args
? * @throws Exception
? */
?public static void main(String[] args) throws Exception {
??// TODO Auto-generated method stub
??Resource rs = new ClassPathResource("beans.xml");
??BeanFactory bf = new XmlBeanFactory(rs);
??HelloI h = (HelloI) bf.getBean("theBean");
??log.info("starting...");
??try {
???log.info(h.sayHello("ma", "bin"));
??} catch (Exception e) {
???e.printStackTrace();
??}
??log.info("end...");
??
??
??ProxyFactory factory=new ProxyFactory();
??factory.addAdvice(new LogThrowAdvice ());
??factory.setTarget(new Hello("hello"));
??try{
??HelloI hi=(HelloI)factory.getProxy();
??hi.sayHello("ma","bin");}
??catch(Exception e){e.printStackTrace();}
?}
}
LogAroundAdvice 通知
package net.blogjava.dodoma.spring.aop;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class LogAroundAdvice implements MethodInterceptor {
?protected static final Log log = LogFactory.getLog(LogAroundAdvice.class);
?public Object invoke(MethodInvocation arg) throws Throwable {
??//?調(diào)用目標(biāo)對(duì)象之前
??log.info("before the target object");
??Object val=arg.proceed();
? //調(diào)用目標(biāo)對(duì)象之后
??log.info("the arg is "+arg);
??log.info("after the target object");
??return val;
?}
}
測(cè)試方法
package net.blogjava.dodoma.spring.aop;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
public class HelloTest {
?protected static final Log log = LogFactory.getLog(HelloTest.class);
?/**
? * @param args
? * @throws Exception
? */
?public static void main(String[] args) throws Exception {
??// TODO Auto-generated method stub
??Resource rs = new ClassPathResource("beans.xml");
??BeanFactory bf = new XmlBeanFactory(rs);
??HelloI h = (HelloI) bf.getBean("theBean");
??log.info("starting...");
??try {
???log.info(h.sayHello("ma", "bin"));
??} catch (Exception e) {
???e.printStackTrace();
??}
??log.info("end...");
??
??
??ProxyFactory factory=new ProxyFactory();
??factory.addAdvice(new LogAroundAdvice ());
??factory.setTarget(new Hello("hello"));
??try{
??HelloI hi=(HelloI)factory.getProxy();
??hi.sayHello("ma","bin");}
??catch(Exception e){e.printStackTrace();}
?}
}
接口和實(shí)現(xiàn)類見LogBeforeAdvice的例子
package net.blogjava.dodoma.spring.aop;
import java.lang.reflect.Method;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.AfterReturningAdvice;
public class LogAfterAdvice implements AfterReturningAdvice {
?protected static final Log log = LogFactory.getLog(LogAfterAdvice.class);
?public void afterReturning(Object returnVal, Method m, Object[] args,
???Object target) throws Throwable {
??// TODO Auto-generated method stub
??log.info("in the class "+this.getClass().getName()+"'s method afterReturning()");
??log.info("the target class is:" + target.getClass().getName());
??log.info("the target method is:" + m.getName());
??for (int i = 0; i < args.length; i++) {
???log.info("the method's args is:" + args[i]);
??}
??
??log.info("the returnValue is "+returnVal);
??//測(cè)試,如果返回裝備發(fā)生了異常.將如何處理程序流程
??//throw new Exception("返回裝備發(fā)生異常");
?}
}
測(cè)試代碼
package net.blogjava.dodoma.spring.aop;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
public class HelloTest {
?protected static final Log log = LogFactory.getLog(HelloTest.class);
?/**
? * @param args
? * @throws Exception
? */
?public static void main(String[] args) throws Exception {
??// TODO Auto-generated method stub
??Resource rs = new ClassPathResource("beans.xml");
??BeanFactory bf = new XmlBeanFactory(rs);
??HelloI h = (HelloI) bf.getBean("theBean");
??log.info("starting...");
??try {
???log.info(h.sayHello("ma", "bin"));
??} catch (Exception e) {
???e.printStackTrace();
??}
??log.info("end...");
??
??
??ProxyFactory factory=new ProxyFactory();
??factory.addAdvice(new LogAfterAdvice());
??factory.setTarget(new Hello("hello"));
??try{
??HelloI hi=(HelloI)factory.getProxy();
??hi.sayHello("ma","bin");}
??catch(Exception e){e.printStackTrace();}
?}
}
在beans.xml中加入如下代碼
<bean id="theLogAfterAdvice" class="net.blogjava.dodoma.spring.aop.LogAfterAdvice"/>
<property name="interceptorNames">
????? <list>
??????? <value>theLogAfterAdvice</value><!--此時(shí)直接使用advice,表明這個(gè)類所有的實(shí)例,方法,都享受advice的攔截-->
?????? </list>?
</property>
切入點(diǎn)可省略,如需要的話
如
<!--切入點(diǎn)-->
? <!--Note: An advisor assembles pointcut and advice-->
? <bean id="theBeAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
??? <property name="advice">
????? <ref local="theLogAfterAdvice"/>
??? </property>
??? <!--匹配模式-->
??? <property name="pattern">
????? <value>.*</value>
??? </property>
? </bean>
接口
package net.blogjava.dodoma.spring.aop;
public interface HelloI {
?public String sayHello(String firstName,String lastName);
?}
實(shí)現(xiàn)類
package net.blogjava.dodoma.spring.aop;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Hello implements HelloI {
?protected static final Log log=LogFactory.getLog(Hello.class);
?private String msg;
?public Hello(){}
?public Hello(String msg){
??this.msg=msg;
?}
?public String getMsg() {
??return msg;
?}
?public void setMsg(String msg) {
??this.msg = msg;
?}
?public String sayHello(String firstName, String lastName) {
??// TODO Auto-generated method stub
??log.info("in the class "+this.getClass().getName()+"'s method sayHello()");
??return (msg+" "+firstName+" "+lastName);
?}
}
BeforeAdvice通知
package net.blogjava.dodoma.spring.aop;
import java.lang.reflect.Method;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.MethodBeforeAdvice;
/**
?* 方法調(diào)用之前.
?* 先調(diào)用此方法
?* @author dodoma
?**/
public class LogBeforeAdvice implements MethodBeforeAdvice {
?protected static final Log log = LogFactory.getLog(LogBeforeAdvice.class);
?public void before(Method m, Object[] args, Object target) throws Throwable {
??log.info("in the class "+this.getClass().getName()+"'s method before()");
??log.info("the target class is:" + target.getClass().getName());
??log.info("the target method is:" + m.getName());
??for (int i = 0; i < args.length; i++) {
???log.info("the method's args is:" + args[i]);
??}
??//測(cè)試,如果在before通知中發(fā)生了異常,程序流程將如何
??//throw new Exception("異常");
?}
}
測(cè)試類
package net.blogjava.dodoma.spring.aop;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
public class HelloTest {
?protected static final Log log = LogFactory.getLog(HelloTest.class);
?public static void main(String[] args) throws Exception {
??// TODO Auto-generated method stub
?//應(yīng)用spring的ioc容器
??Resource rs = new ClassPathResource("beans.xml");
??BeanFactory bf = new XmlBeanFactory(rs);
??HelloI h = (HelloI) bf.getBean("theBean");
??log.info("starting...");
??try {
???log.info(h.sayHello("ma", "bin"));
?????} catch (Exception e) {
???e.printStackTrace();
??}
??log.info("end...");
??
??//如果沒有使用spring的ioc,可以直接用如下代碼測(cè)試
??ProxyFactory factory=new ProxyFactory();
??factory.addAdvice(new LogBeforeAdvice());//添加通知
??factory.setTarget(new Hello("hello"));//添加被代理的類實(shí)例
??try{
??HelloI hi=(HelloI)factory.getProxy();
??hi.sayHello("ma","bin");}
??catch(Exception e){e.printStackTrace();}
?}
}