Tomcat中的设计模式之单例设计模式

在 Tomcat 中,单例设计模式被广泛使用,例如 org.apache.catalina.core.StandardHost 类就是一个单例。

StandardHost 类表示 Tomcat 中的一个虚拟主机,它是 org.apache.catalina.Container 接口的实现类。Tomcat 中的 org.apache.catalina.Container 接口表示一个容器,即一个可以包含其他组件的组件。

在 Tomcat 中,每个 Container 对象都有一个父容器和一组子容器。在 StandardHost 类中,只有一个实例会被创建,并且这个实例会在 Tomcat 启动时被初始化。

以下是 StandardHost 类的一部分代码,展示了如何使用单例模式创建一个唯一的实例:

public class StandardHost extends ContainerBase implements Host {

    /**
     * The application root for this Host.
     */
    protected String appBase = "webapps";

    /**
     * The Java class name of the context configuration class we use.
     */
    protected String contextClass = "org.apache.catalina.core.StandardContext";

    /**
     * The single instance of the Mapper listener that is installed at the host level.
     */
    protected final MapperListener mapperListener = new MapperListener(this);

    /**
     * The set of aliases for this Host.
     */
    protected String[] aliases = new String[0];

    /**
     * The single Servlet instance for this Host.
     */
    protected final transient Context context = (Context) Class.forName(contextClass).newInstance();

    /**
     * The flag that indicates if this host is auto deploy enabled.
     */
    protected boolean autoDeploy = true;

    /**
     * The flag that indicates if this host is deploy on startup.
     */
    protected boolean deployOnStartup = true;

    /**
     * The flag that indicates if this host is deploy XML contexts.
     */
    protected boolean deployXML = true;

    /**
     * The flag that indicates if this host is unpack WARs.
     */
    protected boolean unpackWARs = true;

    /**
     * The set of Valves associated with this Host.
     */
    protected final ValveContext valveContext = new StandardHostValveContext();

    // 构造函数私有化,防止外部创建实例
    private StandardHost() {
        super();
        pipeline.setBasic(new StandardHostValve());
        cluster = new SimpleTcpCluster();
    }

    /**
     * The singleton instance of this class.
     */
    private static StandardHost instance;

    /**
     * Returns the singleton instance of this class.
     */
    public static synchronized StandardHost getInstance() {
        if (instance == null) {
            instance = new StandardHost();
        }
        return instance;
    }

    /**
     * Starts this host.
     */
    public void start() throws LifecycleException {
        if (!started) {
            // 设置状态
            setState(LifecycleState.STARTING);
            // 初始化相关配置
            init();
            // 启动相关组件
            super.start();
        }
    }
    // ...
}

在上面的代码中,StandardHost 类的构造函数是私有的,这意味着外部代码无法创建 StandardHost 对象。而在 getInstance() 方法中,如果实例不存在,则会创建一个新的 StandardHost 实例,并将其保存在 instance 变量中。这样,无论多少次调用