java的内部类

内部类
http://www.blogjava.net/RogerTwain/archive/2007/05/23/119456.html
应用场景

1 不想被外部访问的时候
2 可能要不断的调用某个方法来返回自己
[ccn lang="java" tab_size="4" theme="blackboard" width="550" ]
package com.wideplay.warp.servlet;

import com.google.inject.AbstractModule;
import com.google.inject.Key;
import com.google.inject.Module;
import com.wideplay.warp.servlet.uri.UriPatternType;
import net.jcip.annotations.NotThreadSafe;

import javax.servlet.Filter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Created with IntelliJ IDEA.
* User: dhanji
* Date: Dec 19, 2007
* Time: 5:53:46 PM
* 过滤器module的构造器 FilterBindingBuilder的实现 继承了google的AbstractModule
* @author Dhanji R. Prasanna (dhanji gmail com)
*/
@NotThreadSafe //intended to be confined to a single thread and disposed after injector creation
class FiltersModuleBuilder extends AbstractModule implements FilterBindingBuilder {
private List filterDefinitions = new ArrayList();

//invoked on injector config
protected void configure() {
//bind these filter definitions to a config placeholder object
bind(ManagedFilterPipeline.class)
.toInstance(new ManagedFilterPipeline(filterDefinitions));
}

//the first level of the EDSL--
//默认的是绑定servlet的
public FilterKeyBindingBuilder filter(String urlPattern) {
return new FilterKeyBindingBuilderImpl(urlPattern, UriPatternType.SERVLET);
}

public FilterKeyBindingBuilder filterRegex(String regex) {
return new FilterKeyBindingBuilderImpl(regex, UriPatternType.REGEX);
}

public ServletBindingBuilder servlets() {
return new ServletsModuleBuilder(this);
}

//shortcut method if there are no servlets to configure
//如果没有servlets需要去配置的话
public Module buildModule() {
return new ServletsModuleBuilder(this);
}
//FilterKeyBindingBuilder的实现 一个存放需要匹配的url 一个存放匹配的类型 在这里默认是使用UriPatternType.SERVLET的
//non-static inner class so it can access state of enclosing module class
private class FilterKeyBindingBuilderImpl implements FilterKeyBindingBuilder {
private final String uriPattern;
private final UriPatternType uriPatternType;

private FilterKeyBindingBuilderImpl(String uriPattern, UriPatternType uriPatternType) {
this.uriPattern = uriPattern;
this.uriPatternType = uriPatternType;
}

public FilterBindingBuilder through(Class filterKey) {
return through(Key.get(filterKey));
}

public FilterBindingBuilder through(Key filterKey) {
return through(filterKey, new HashMap());
}

public FilterBindingBuilder through(Class filterKey, Map contextParams) {
//careful you don't accidentally make this method recursive!! thank you IntelliJ IDEA!
return through(Key.get(filterKey), contextParams);
}

public FilterBindingBuilder through(Key filterKey, Map contextParams) {
filterDefinitions.add(new FilterDefinition(uriPattern, filterKey, UriPatternType.get(uriPatternType), contextParams));

return FiltersModuleBuilder.this;
}
}
}

[/ccn]
这里的调用
看例子
.filter("/*").through(WidgetFilter.class)
最终返回的还是this 可以继续调用同样的方法来完成一些装配类似的工作
3 适当使用内部类,使得代码更加灵活和富有扩展性
适当的使用内部类,可以使得你的代码更加灵活和富有扩展性。当然,在这里头起作用的还是一些模式的运行,但如果不配以内部类的使用,这些方法的使用效果就差远了。不信?请看下面的例子:
我们记得简单工厂模式的作用就是将客户对各个对象的依赖转移到了工厂类里。很显然,简单工厂模式并没有消除那些依赖,只是简单的将它们转移到了工厂类里。如果有新的对象增加进来,则我们需要修改工厂类。所以我们需要对工厂类做进一步的改造,进一步消除它对具体类的依赖。以前我们提供过一个使用反射来消除依赖的方法;这里,我们将提供另外一种方法。
这种方法是将工厂进一步抽象,而将具体的工厂类交由具体类的创建者来实现,这样,工厂类和具体类的依赖的问题就得到了解决。而工厂的使用者则调用抽象的工厂来获得具体类的对象。如下。
我们以一个生产形体的工厂为例,下面是这些形体的接口:
[ccn lang="java" tab_size="4" theme="blackboard" width="550" ]
package polyFactory;

public interface Shape {
public void draw();
public void erase();

}
[/ccn]
通过上面的描述,大家都可能已经猜到,这个抽象的工厂肯定使用的是模板方法模式。如下:
[ccn lang="java" tab_size="4" theme="blackboard" width="550" ]
package polyFactory;

import java.util.HashMap;
import java.util.Map;

public abstract class ShapeFactory {
protected abstract Shape create();
private static Map factories = new HashMap();
public static void addFactory(String id,ShapeFactory f)
{
factories.put(id,f);
}
public static final Shape createShape(String id)
{
if(!factories.containsKey(id))
{
try
{
Class.forName("polyFactory."+id);
}
catch(ClassNotFoundException e)
{
throw new RuntimeException("Bad shape creation : "+id);
}
}
return ((ShapeFactory)factories.get(id)).create();
}
}
[/ccn]
不错,正是模板方法模式的运用。这个类蛮简单的:首先是一个create()方法,用来产生具体类的对象,留交各具体工厂实现去实现。然后是一个Map类型的静态变量,用来存放具体工厂的实现以及他们的ID号。接着的一个方法使用来增加一个具体工厂的实现。最后一个静态方法是用来获取具体对象,里面的那个Class.forName……的作用是调用以ID号为类名的类的一些静态的东西。
下面,我们来看具体的类的实现:
[ccn lang="java" tab_size="4" theme="blackboard" width="550" ]
package polyFactory;

public class Circle implements Shape {

public void draw() {
// TODO Auto-generated method stub
System.out.println("the circle is drawing...");
}

public void erase() {
// TODO Auto-generated method stub
System.out.println("the circle is erasing...");
}
private static class Factory extends ShapeFactory
{
protected Shape create()
{
return new Circle();
}
}
static {ShapeFactory.addFactory("Circle",new Factory());}

}
[/ccn]
这个类的其他的地方也平常得很。但就是后面的那个内部类Factory用得好。第一呢,这个类只做一件事,就是产生一个Circle对象,与其他类无关,就这一个条也就满足了使用内部类的条件。第二呢,这个Factory类需要是静态的,这也得要求它被使用内部类,不然,下面的ShapeFacotry.addFactory就没办法add了。而最后的那个静态的语句块是用来将具体的工厂类添加到抽象的工厂里面去。在抽象工厂里调用Class.forName就会执行这个静态的语句块了。
下面仍然是一个具体类:
[ccn lang="java" tab_size="4" theme="blackboard" width="550" ]
package polyFactory;

public class Square implements Shape {

public void draw() {
// TODO Auto-generated method stub
System.out.println("the square is drawing...");
}

public void erase() {
// TODO Auto-generated method stub
System.out.println("the square is erasing...");
}
private static class Factory extends ShapeFactory
{
protected Shape create()
{
return new Square();
}
}
static {ShapeFactory.addFactory("Square",new Factory());}

}
[/ccn]
最后,我们来测试一下:
[ccn lang="java" tab_size="4" theme="blackboard" width="550" ]
String[] ids = new String[]{"Circle","Square","Square","Circle"};
for(int i=0;i