设计模式之三:工厂方法模式—多态工厂的实现
2016-09-22 15:25
555 查看
简单工厂的严重问题:
当系统中需要引进新产品时,静态工厂方法通过所传入参数的不同来创建不同的产品,这必定要修改工厂类的源代码,违背了开闭原则
引入工厂方法模式:
针对不同的产品提供不同的工厂
定义:
定义一个用于创建对象的接口,让子类决定将 哪一个类实例化,工厂方法迷失让一个类实例化延迟到其子类,工厂方法模式又称为工厂模式(Factory Pattern),又课称作虚拟构造器模式(VIrtual Constructor Pattern)
一、工厂方法模式概述:
引入抽象工厂角色,可以是接口,也可以是抽象类或者具体类
代码:
interface Factory{
public Product factoryMethod();
}
class ConcreteFactory implements Factory{
public Product factoryMethod(){
return new COncreteFactory();
}
}
二、完整解决方案:
interface Logger{
public void writeLog();
}
class DatabaseLogger implements Logger{
public void writeLog(){
System.out.println("数据库写日志");
}
}
class FileLogger implements Logger{
public void writeLog(){
System.out.println("文件写日志");
}
}
interface LoggerFactory{
public Logger createLogger();
}
class DatabaseLoggerFactory implements Factory{
public Logger createLogger(){
Logger logger =new DatabaseLogger();
return logger();
}
}
class FileLoggerFactory implements Factory{
public Logger createLogger(){
Logger logger=new FileLogger();
return logger;
}
}
class Client{
public static void main(String[] args) {
LoggerFactory factory;
Logger logger;
factory=new FileLoggerFactory();
logger=factory.createLogger();
logger.writeLog()
}
}
三、反射与配置文件
利用反射,返回xml中指定的对象,这样修改就不用修改源码了。
<?xml version="1.0"?>
<config>
<chartType>histogram</chartType>
</config>
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.*;
class XMLUtil{
public static String getChartType(){
try{
DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();
DocumentBuilder builer=dFactory.newDocumentBuilder();
Document doc;
doc=builer.parse(new File("config.xml"));
NodeList nl=doc.getElementsByTagName("className");
Node classNode=nl.item(0).getFirstChild();
String cName=classNode.getNodeValue();
Class c=Class.forName(cName);
Object obj=c.newInstance();
return obj;
}
catch(Exception e){
e.printStackTrace();
return null;
}
}
}
Client端修改如下:
class Client{
public static void main(String[] args) {
LoggerFactory factory;
Logger logger;
factory=(LoggerFactory)XMLUtil.getBean;
logger=factory.createLogger();
logger.writeLog()
}
四、重载的工厂方法
使用工厂创建对象时,创建方法可以重载,使用args参数,obj参数,默认方式等多种参数来创建工厂
class DatabaseLoggerFactory implements Factory{
public Logger createLogger(){
Logger logger =new DatabaseLogger();
return logger();
}
public Logger createLogger(String args){
Logger logger =new DatabaseLogger();
return logger();
}
public Logger createLogger(Object obj){
Logger logger =new DatabaseLogger();
return logger();
}
}
五、工厂方法模式总结:
主要优点:
用火狐只需关心产品对应的工厂,无需关心创建细节,甚至具体产品的类的类名
多态,所有具体工厂类都具有同一个父类
加入新产品时,无需修改抽象工厂和抽象产品听的接口,无需修改客户端,也无需修改其他的具体工厂和具体产品,而指套添加一个具体工厂和具体产品就可以了,扩展性好
主要缺点:
添加新产品时徐太编写新的具体产品类
为了扩展性,需要引入抽象层,增加系统的抽象性和理解难度,增加了实现的难度
适用场景:
客户端不知道其所需要的对象的类
抽象工厂类通过其子类来指定创建那个对象
当系统中需要引进新产品时,静态工厂方法通过所传入参数的不同来创建不同的产品,这必定要修改工厂类的源代码,违背了开闭原则
引入工厂方法模式:
针对不同的产品提供不同的工厂
定义:
定义一个用于创建对象的接口,让子类决定将 哪一个类实例化,工厂方法迷失让一个类实例化延迟到其子类,工厂方法模式又称为工厂模式(Factory Pattern),又课称作虚拟构造器模式(VIrtual Constructor Pattern)
一、工厂方法模式概述:
引入抽象工厂角色,可以是接口,也可以是抽象类或者具体类
代码:
interface Factory{
public Product factoryMethod();
}
class ConcreteFactory implements Factory{
public Product factoryMethod(){
return new COncreteFactory();
}
}
二、完整解决方案:
interface Logger{
public void writeLog();
}
class DatabaseLogger implements Logger{
public void writeLog(){
System.out.println("数据库写日志");
}
}
class FileLogger implements Logger{
public void writeLog(){
System.out.println("文件写日志");
}
}
interface LoggerFactory{
public Logger createLogger();
}
class DatabaseLoggerFactory implements Factory{
public Logger createLogger(){
Logger logger =new DatabaseLogger();
return logger();
}
}
class FileLoggerFactory implements Factory{
public Logger createLogger(){
Logger logger=new FileLogger();
return logger;
}
}
class Client{
public static void main(String[] args) {
LoggerFactory factory;
Logger logger;
factory=new FileLoggerFactory();
logger=factory.createLogger();
logger.writeLog()
}
}
三、反射与配置文件
利用反射,返回xml中指定的对象,这样修改就不用修改源码了。
<?xml version="1.0"?>
<config>
<chartType>histogram</chartType>
</config>
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.*;
class XMLUtil{
public static String getChartType(){
try{
DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();
DocumentBuilder builer=dFactory.newDocumentBuilder();
Document doc;
doc=builer.parse(new File("config.xml"));
NodeList nl=doc.getElementsByTagName("className");
Node classNode=nl.item(0).getFirstChild();
String cName=classNode.getNodeValue();
Class c=Class.forName(cName);
Object obj=c.newInstance();
return obj;
}
catch(Exception e){
e.printStackTrace();
return null;
}
}
}
Client端修改如下:
class Client{
public static void main(String[] args) {
LoggerFactory factory;
Logger logger;
factory=(LoggerFactory)XMLUtil.getBean;
logger=factory.createLogger();
logger.writeLog()
}
四、重载的工厂方法
使用工厂创建对象时,创建方法可以重载,使用args参数,obj参数,默认方式等多种参数来创建工厂
class DatabaseLoggerFactory implements Factory{
public Logger createLogger(){
Logger logger =new DatabaseLogger();
return logger();
}
public Logger createLogger(String args){
Logger logger =new DatabaseLogger();
return logger();
}
public Logger createLogger(Object obj){
Logger logger =new DatabaseLogger();
return logger();
}
}
五、工厂方法模式总结:
主要优点:
用火狐只需关心产品对应的工厂,无需关心创建细节,甚至具体产品的类的类名
多态,所有具体工厂类都具有同一个父类
加入新产品时,无需修改抽象工厂和抽象产品听的接口,无需修改客户端,也无需修改其他的具体工厂和具体产品,而指套添加一个具体工厂和具体产品就可以了,扩展性好
主要缺点:
添加新产品时徐太编写新的具体产品类
为了扩展性,需要引入抽象层,增加系统的抽象性和理解难度,增加了实现的难度
适用场景:
客户端不知道其所需要的对象的类
抽象工厂类通过其子类来指定创建那个对象
相关文章推荐
- PropertyChangeListener简单理解
- 什么是设计模式
- 设计模式之创建型模式 - 特别的变量问题
- 七、设计模式——装饰模式
- 设计模式总结
- 设计模式之创建型模式
- 浅谈设计模式的学习
- 设计模式---状态模式在web前端中的应用
- Ruby设计模式编程之适配器模式实战攻略
- 实例讲解Ruby使用设计模式中的装饰器模式的方法
- 设计模式中的模板方法模式在Ruby中的应用实例两则
- Ruby设计模式编程中对外观模式的应用实例分析
- 实例解析Ruby设计模式编程中Strategy策略模式的使用
- Ruby中使用设计模式中的简单工厂模式和工厂方法模式
- Ruby使用设计模式中的代理模式与装饰模式的代码实例
- 详解组合模式的结构及其在Ruby设计模式编程中的运用
- C# 设计模式系列教程-建造者模式
- C#编程中使用设计模式中的原型模式的实例讲解
- 使用设计模式中的工厂方法模式进行C#编程的示例讲解
- 实例解析C#设计模式编程中简单工厂模式的使用