工厂方法源码解析(jdk+logback)

我们来看一下Collection,这个类大家都比较熟悉,

public interface Collection<E> extends Iterable<E> {

是集合类,例如在这个接口中定义的Iterator接口,

Iterator<E> iterator();

这个方法就是一个工厂方法,Collection可以理解成一个抽象工厂,那在后面讲抽象工厂的时候呢,我们再重点关注抽象工厂,

而现在我们只关注工厂方法,工厂方法这个词可以理解为作为工厂的一个方法,而Iterator这个方法呢,正是作为工厂的一个方法,

这是一个接口,接口里面的一个方法,那他有很多实现类,例如ArrayList这里边,对于iterator()方法的一个实现

public Iterator<E> iterator() {
	return new Itr();
}
	
这里面只用了一个内部类来实现,private class Itr implements Iterator<E> 就是这个,

这里面就是全交由子类来实现了,使用不同工厂类中的iterator方法能够得到不同的具体产品的实例,

我们可以认为ArrayList在这里边是一个具体的实现工厂,他呢实现了这个工厂方法,而具体的抽象产品呢,又是Iterator这么一个接口,

public interface Iterator<E> 

具体抽象产品已经找到,那实际生产出来的产品呢,那就是ArrayList里面的Itr对象,private class Itr implements Iterator<E>

这个就是具体的产品,他实现了Iterator接口,然后这里边写这么一个实现,同时在具体的工厂里面,返回了具体的产品,这个产品

也就是说Iterator抽象产品的一个实例,我们可以类比来看,Collection相当于我们里面的VideoFactory,ArrayList就相当于具体的

实现工厂,例如JavaVideoFactory,PathonVideoFactory,而抽象产品,就是Iterator这么一个产品,而在我们的课程当中,就是Video

这么一个抽象类,它是一个抽象产品,然后实际的具体产品就是ArrayList里面的Itr这么一个类,他实现了抽象产品,那Itr对应我们工厂

里面的,就是JavaVideo,PathonVideo,或者FEVideo,那我们看一下,Itr这么一个类图

抽象产品,具体的ArrayList Itr实际的产品,而这个类是和ArrayList是有依赖关系的,也就是说ArrayList依赖他,

因为Itr作为iterator方法的一个返回值,也就是说这个Itr类型虽然是Iterator这个接口类型,但是它是一个具体的产品,

public Iterator<E> iterator() {
	return new Itr();
}

private class Itr implements Iterator<E>

例如这里可以看出来,那我们来看一下ArrayList的一个类图

从这里面就可以看出来,ArrayList实现的一个接口,以及和其他抽象类的一个关系,那我们重点来关注一个方法,

我们看一下ArrayList的方法,我们找到iterator这么一个方法,也就是说ArrayList中的iterator方法

我们可以人工的看一下他们之间的关系,通过里面的类实现,他们之间的关系,所以这个就是一个工厂方法,在JDK重要的体现,

那我们现在看另外一个类,public interface URLStreamHandlerFactory 这样一个类,首先它是一个接口,这个类在JDK里面

主要是解决URL协议扩展使用的,这里面的protocol也就决定了交互规范,例如HTTP FILE,https,这些呢都是协议,那我们现在

来理解一下,很明显它是一个工厂,并且这个工厂里面只有一个方法

public interface URLStreamHandlerFactory {
    /**
     * Creates a new {@code URLStreamHandler} instance with the specified
     * protocol.
     *
     * @param   protocol   the protocol ("{@code ftp}",
     *                     "{@code http}", "{@code nntp}", etc.).
     * @return  a {@code URLStreamHandler} for the specific protocol.
     * @see     java.net.URLStreamHandler
     */
    URLStreamHandler createURLStreamHandler(String protocol);
}

之前也说了,无法具体描述的话,我们使用抽象类和抽象方法也可以,使用一个接口和一个方法命名,也是OK的,那么我们来看看他的

具体实现,

Launcher Factory createURLStreamHandler

private static class Factory implements URLStreamHandlerFactory {
    private static String PREFIX = "sun.net.www.protocol";

    private Factory() {
    }

    public URLStreamHandler createURLStreamHandler(String var1) {
        String var2 = PREFIX + "." + var1 + ".Handler";

        try {
            Class var3 = Class.forName(var2);
            return (URLStreamHandler)var3.newInstance();
        } catch (ReflectiveOperationException var4) {
            throw new InternalError("could not load " + var1 + "system protocol handler", var4);
        }
    }
}

这个Factory是一个静态类,实现了URLStreamHandlerFactory,这里面定义了一个前缀,这个前缀就是给具体的类使用的,

比如说这个是一个包名,然后点,再加上var1,然后.Handler,为什么点Handler呢,以后我们来看一下,Class.forName,

newInstance,来找到具体的产品,那前面我们讲简单工厂的时候,通过Class.forName,对简单工厂进行了一个扩展,

我们看一下他的返回值是URLStreamHandler,而这个类呢如果实现工厂的话,可以大胆猜测一下,他会不会是一个抽象类呢,

或者说作为很多类的一个父类,我们点进来看一下,URLStreamHandler他是一个抽象类

然后下边有openConnection,是一个比较主要的方法

既然他返回的是一个抽象类

public abstract class URLStreamHandler {
    /**
     * Opens a connection to the object referenced by the
     * {@code URL} argument.
     * This method should be overridden by a subclass.
     *
     * <p>If for the handler's protocol (such as HTTP or JAR), there
     * exists a public, specialized URLConnection subclass belonging
     * to one of the following packages or one of their subpackages:
     * java.lang, java.io, java.util, java.net, the connection
     * returned will be of that subclass. For example, for HTTP an
     * HttpURLConnection will be returned, and for JAR a
     * JarURLConnection will be returned.
     *
     * @param      u   the URL that this connects to.
     * @return     a {@code URLConnection} object for the {@code URL}.
     * @exception  IOException  if an I/O error occurs while opening the
     *               connection.
     */
    abstract protected URLConnection openConnection(URL u) throws IOException;
	
他肯定是由子类来实现他的,这里面有N多Handler,有deploy发布包下面的

下面还有具体的协议,protocol.file协议,ftp协议,http,https,mial各种协议

我们先进入http的Handler

这个Handler直接继承了这个抽象类,那这个Handler里边啊,openConnection方法抽象方法,并且它是一个protected,

所以子类必须会实现他,也就是说openConnection,这个是http包下面的Handler,那我们再看一下其他的实现类,例如

有一个https的

它是间接继承,这个handler我们进来

继承下一个Handler,再进来

这样Handler继承了URLStreamHandler,这个factory里面继承了这个

public interface URLStreamHandlerFactory {
    /**
     * Creates a new {@code URLStreamHandler} instance with the specified
     * protocol.
     *
     * @param   protocol   the protocol ("{@code ftp}",
     *                     "{@code http}", "{@code nntp}", etc.).
     * @return  a {@code URLStreamHandler} for the specific protocol.
     * @see     java.net.URLStreamHandler
     */
    URLStreamHandler createURLStreamHandler(String protocol);
}

里面提供了工厂方法,而createURLStreamHandler这个工厂方法的实现

里面通过Class.forName来获取对象,而具体对象就是URLStreamFactory很多实现的一个子类

那我们现在来对应一下,URLStreamHandler对应我们的Video,这个是抽象的产品,而这些都是具体的产品,

URLStreamHandlerFactory,对应的就是VideoFactory,这里面提供了一个方法,而这个方法createURLStreamHandler

具体的实现呢,交由他的子类,Launcher这个类来实现的

而具体这个方法的实现,也就是这个工厂的实现

public interface URLStreamHandlerFactory {
    /**
     * Creates a new {@code URLStreamHandler} instance with the specified
     * protocol.
     *
     * @param   protocol   the protocol ("{@code ftp}",
     *                     "{@code http}", "{@code nntp}", etc.).
     * @return  a {@code URLStreamHandler} for the specific protocol.
     * @see     java.net.URLStreamHandler
     */
    URLStreamHandler createURLStreamHandler(String protocol);
}

就是使用Factory这么一个类

他实现了URLStreamHandlerFactory,这个Factory就相当于我们的JavaVideoFactory,PythonVideFactory,所以工厂方法

所在的类,还有具体的创建者,还有抽象的产品,和具体的产品,我们都找到了,那这一部分也是工厂方法,在JDK中的一个重要体现,

我们再看logback中的一些应用

public interface ILoggerFactory {
  
  /**
   * Return an appropriate {@link Logger} instance as specified by the
   * <code>name</code> parameter.
   * 
   * <p>If the name parameter is equal to {@link Logger#ROOT_LOGGER_NAME}, that is 
   * the string value "ROOT" (case insensitive), then the root logger of the 
   * underlying logging system is returned.
   * 
   * <p>Null-valued name arguments are considered invalid.
   *
   * <p>Certain extremely simple logging systems, e.g. NOP, may always
   * return the same logger instance regardless of the requested name.
   * 
   * @param name the name of the Logger to return
   * @return a Logger instance 
   */
  public Logger getLogger(String name);
}

这个接口下边只有一个方法,我们看一下他的实现,在这三个类中

也就是把这个抽象方法教给子类来实现,我们来看一下类图

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值