关于设计模式的学习笔记,教材:《设计模式的艺术之道》 刘伟 著
工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又简称为工厂模式,又可称作虚拟构造器模式(Virtual Constructor)或多态工厂模式(Polymorphic factory pattern)。工厂方法模式一种类创建型模式。
例题:使用工厂方法模式设计一个程序来读取各种不同类型的图片格式,针对每一种图片格式都设计一个图片读取器,例如GIF图片读取器用于读取GIT格式的图片,JPG图片读取器用于读取JPG格式的图片。
<?xml version="1.0"?>
<config> <imgReaderFactory>designPattern.FactoryMethod.GIFReaderFactory</imgReaderFactory>
</config>
public class XMLUtil {
public static Object getImgReader() {
try {
//创建文档对象
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document document = builder.parse(new File("config.xml"));
NodeList nodeList = document.getElementsByTagName("imgReaderFactory");
Node node = nodeList.item(0).getFirstChild();
String className = node.getNodeValue().trim();
Class c=Class.forName(className);
Object o=c.newInstance();
return o;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
public interface ImageReader {
void readImg(String fileName);
}
public class JpgReader implements ImageReader {
@Override
public void readImg(String fileName) {
System.out.println("JPG图片读取器读取"+fileName);
}
public JpgReader(){}
}
public class GifReader implements ImageReader {
@Override
public void readImg(String fileName) {
System.out.println("GIF图片读取器读取"+fileName);
}
public GifReader(){}
}
public interface ReaderFactory {
ImageReader createReader();
}
public class JPGReaderFactory implements ReaderFactory {
@Override
public ImageReader createReader() {
//配置环境等 比如连接数据库
ImageReader reader=new JpgReader();
//初始化reader的数据等
return reader;
}
}
public class GIFReaderFactory implements ReaderFactory {
@Override
public ImageReader createReader() {
//配置环境等 比如连接数据库
ImageReader reader=new GifReader();
//初始化reader的数据等
return reader;
}
}
public class Test {
public static void main(String[] args){
ReaderFactory factory= (ReaderFactory) XMLUtil.getImgReader();
ImageReader reader=factory.createReader();
reader.readImg("1.???");
//输出 GIF图片读取器读取1.???
}
}
思考:
有人说:可以在客户端代码中直接通过反射机制来生成产品对象,在定义产品对象时使用抽象类型,同样可以确保系统的灵活性和可拓展性,增加新的具体产品类无序修改源代码,只需要将其作为抽象产品类的子类再修改配置文件即可,根本不需要抽象工厂类和具体工厂类。
试思考,这种方法是否可行?是否存在问题?
我的思考:这样做的话,类的创建和使用就在同一个类,不符合单一职责原则,但这样似乎也没什么吧?或者说有些初始化工作不应该在构造函数内。(如果使用上述方法,初始化工作不能放在工厂里,只能放在构造函数内了)
我对上面文章的理解是:实际应用中,类的创建往往没有反射生成对象这样简单,一般需要在创建之前配置环境(连接数据库?没有相应经验,不太清楚)创建之后还要进行初始化操作,而这些是不适宜放在构造函数内的,因为单一职责原则,降低类的粒度。也不适宜放在客户端那,不然会造成冗余。
工厂就很好的将对象的创建和使用分离了。
还有一个好处是,一个类可能拥有多个构造函数,我们不需要去理解那些复杂的参数列表,而只需要使用工厂提供的名字完全不同的工厂方法即可,这样提高了可读性。