GOF:工厂模式是一种对象创建型模式,它把类的实例的创建延迟到子类中完成,父工厂类只定义创建对象的公共接口,而子工厂类则负责生成具体的类的实例。
工厂方法是一种创建性模式,它定义了一个创建对象的接口,但是却让子类来决定具体实例化哪一个类.当一个类无法预料要创建哪种类的对象或是一个类需要由子类来指定创建的对象时我们就需要用到Factory Method 模式了.简单说来,Factory Method可以根据不同的条件产生不同的实例,当然这些不同的实例通常是属于相同的类型,具有共同的父类.Factory Method把创建这些实例的具体过程封装起来了,简化了客户端的应用,也改善了程序的扩展性,使得将来可以做最小的改动就可以加入新的待创建的类. 通常我们将Factory Method作为一种标准的创建对象的方法,当发现需要更多的灵活性的时候,就开始考虑向其它创建型模式转化.
工厂方法的一个典型例子:迭代器
迭代器模式提供了一种顺序访问集合中的元素的方法,然而通常用iterator()方法本身却是一个工厂方法模式的很好的例子,该方法使得调用方无需了解所要实例化的类,JDK引入了collection()接口,该接口包含了一个iterator()方法,所有的集合都要实现该接口,通过集合创建了一个对象,该对象返回集合中的各个元素的序列,例如,下面的代码创建了一个列表对象,并将他的元素打印出来.
在工厂方法模式中,工厂方法的用户不必知道该实例化那个类,上面的iterator()方法很好的示范了这个特性.
呵呵上面那个例子可能太抽象了,下面结合书上的祥细的例子讲解了.
日志记录是软件开发中常用的功能之一,我们有时候需要日志向打到控制台,有时侯打到文件了,因此将实际的日志的记录功能保留在公共的程序内部是一个很好的想法了,这样客户机对象就无需重复这些详细信息.定义一个JAVA接口Logger,声明该接口有客户机对象用于记录消息,一般来说.进来的消息可以按不同的格式记录到不同的输出的介质上,因为Logger接口的不同具体实现者类可以在实施中处理这些差异,定义这两个实施者.Logger接口代码如下:
Logger实施者代码如下:
作为工厂方法实施的一部分,工厂方法法getLogger会检查logger.properties属性文件以查看是否启用文件记录的功能.并决定要选定那个Logger实施者将作为Logger类型的对象返回.
使用工厂方法,客户机对象无需处理选择和例示相应的Logger实施者出现的复杂状况.也无需了解Logger接口的不同实施者的存在性及相关功能.LoggerFactory代码如下:
工厂方法是一种创建性模式,它定义了一个创建对象的接口,但是却让子类来决定具体实例化哪一个类.当一个类无法预料要创建哪种类的对象或是一个类需要由子类来指定创建的对象时我们就需要用到Factory Method 模式了.简单说来,Factory Method可以根据不同的条件产生不同的实例,当然这些不同的实例通常是属于相同的类型,具有共同的父类.Factory Method把创建这些实例的具体过程封装起来了,简化了客户端的应用,也改善了程序的扩展性,使得将来可以做最小的改动就可以加入新的待创建的类. 通常我们将Factory Method作为一种标准的创建对象的方法,当发现需要更多的灵活性的时候,就开始考虑向其它创建型模式转化.
工厂方法的一个典型例子:迭代器
迭代器模式提供了一种顺序访问集合中的元素的方法,然而通常用iterator()方法本身却是一个工厂方法模式的很好的例子,该方法使得调用方无需了解所要实例化的类,JDK引入了collection()接口,该接口包含了一个iterator()方法,所有的集合都要实现该接口,通过集合创建了一个对象,该对象返回集合中的各个元素的序列,例如,下面的代码创建了一个列表对象,并将他的元素打印出来.
public class ShowIterator{
public static void mian(String args[]){
List list=Array.asList(new String[]{"foundation","rocket","sparkler"});
Iterator i=list.iterator();
while(i.hasNext()){
System.out.prinltn(i.next());
}
}
}
在工厂方法模式中,工厂方法的用户不必知道该实例化那个类,上面的iterator()方法很好的示范了这个特性.
呵呵上面那个例子可能太抽象了,下面结合书上的祥细的例子讲解了.
日志记录是软件开发中常用的功能之一,我们有时候需要日志向打到控制台,有时侯打到文件了,因此将实际的日志的记录功能保留在公共的程序内部是一个很好的想法了,这样客户机对象就无需重复这些详细信息.定义一个JAVA接口Logger,声明该接口有客户机对象用于记录消息,一般来说.进来的消息可以按不同的格式记录到不同的输出的介质上,因为Logger接口的不同具体实现者类可以在实施中处理这些差异,定义这两个实施者.Logger接口代码如下:
public interface Logger {
public void log(String msg);
}
Logger实施者代码如下:
public class ConsoleLogger implements Logger {
@Override
public void log(String msg) {
// TODO Auto-generated method stub
System.out.println(msg);
}
}
public class FileLogger implements Logger {
@Override
public void log(String msg) {
// TODO Auto-generated method stub
File futil=new FileUtil();
futil.writeToFile("log.txt",msg,true,true);
}
}
应用工厂方法模式,选择相应的Logger实施者所需的实施可以封装在单独类LoggerFactory中的单独方法getLogger工厂方法的内部.
作为工厂方法实施的一部分,工厂方法法getLogger会检查logger.properties属性文件以查看是否启用文件记录的功能.并决定要选定那个Logger实施者将作为Logger类型的对象返回.
使用工厂方法,客户机对象无需处理选择和例示相应的Logger实施者出现的复杂状况.也无需了解Logger接口的不同实施者的存在性及相关功能.LoggerFactory代码如下:
import java.io.IOException;
import java.util.Properties;
public class LoggerFactory {
public boolean isFileLoggingEnabled(){
Properties p=new Properties();
try{
p.load(ClassLoader.getSystemResourceAsStream("Logger.properties"));
String fileLoggingValue=p.getProperty("FileLogging");
if(fileLoggingValue.equalsIgnoreCase("ON")==true)
return true;
else
return false;
}catch (IOException e){
return false;
}
}
//Factory Method
public Logger getLogger(){
if(isFileLoggingEnabled()){
return new FileLogger();
}else {
return new ConsoleLogger();
}
}
}
客户机LoggerTest代码如下:
public class LoggerTest {
public static void main(String args[]){
LoggerFactory factory=new LoggerFactory();
Logger logger=factory.getLogger();
logger.log("A Message to Log");
}
}
在本应用中,我们使用工厂方法的默认实施将创建者类LoggerFactory设计为具体的类。我的感受是在工厂类中完成客户机的类选择功能,这样让客户机不用知道自己去选择那个类,我觉的这也是接口的一个用法!