我们来看一下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);
}
这个接口下边只有一个方法,我们看一下他的实现,在这三个类中
也就是把这个抽象方法教给子类来实现,我们来看一下类图