zoukankan      html  css  js  c++  java
  • 设计模式之工厂方法模式(附实例代码下载)

    工厂方法模式继承了简单工厂模式的优点,还弥补了简单工厂模式的缺陷

    关于简单工厂模式请戳这里!

    工厂方法模式的定义:定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化,工厂方法模式让一个类的实例化延迟到其子类

    简而言之就是工厂方法模式有多个子工厂,每个子工厂负责一个产品的生产,这些子工厂都有一个父类:抽象工厂

    工厂方法模式包括四个角色:

    1)抽象产品

    2)具体产品

    3)抽象工厂

    4)具体工厂

    不同的具体工厂可以创建不同的具体产品,当然,在实际使用时,具体工厂类在实现工厂方法时除了创建具体产品对象之外,还可以负责产品对象的初始化工作以及一些资源和环境配置工作,例如连接数据库,创建文件等

    可以通过配置文件来储存具体工厂类的类名,再通过反射机制创建具体的工厂对象,这样在更新的具体工厂时无需修改源码,系统扩展更加方便

    实例如下:

    实例说明:模拟建设一个日志记录器,包括数据库日志记录器,文件日志记录器

    1.日志记录器接口 充当抽象产品角色 

    package 工厂方法模式;
    /**
     *@author YB
     *@version 2019年3月16日下午3:08:18    
     */
    /*
     * 日志记录器接口 充当抽象产品角色
     */
    public interface Logger {
        public void writelog();//接口定义的方法
    }

    2.数据库日志记录器,充当具体产品角色

    package 工厂方法模式;
    /**
     *@author YB
     *@version 2019年3月16日下午3:09:54    
     */
    /*
     * 数据库日志记录器,充当具体产品角色
     */
    public class Databaselogger implements Logger {
    
        @Override
        public void writelog() {
            // TODO Auto-generated method stub
            System.out.println("数据库日志记录");
        }
    
    }

     3.文件日志记录器,充当具体产品角色

    package 工厂方法模式;
    /**
     *@author YB
     *@version 2019年3月16日下午3:11:16    
     */
    /*
     * 文件日志记录器,充当具体产品角色
     */
    public class FileLogger implements Logger{
    
        @Override
        public void writelog() {//实现接口方法
            // TODO Auto-generated method stub
            System.out.println("文件日志记录");
        }
        
    }

     4.日志记录器工厂接口,充当抽象工厂角色

    package 工厂方法模式;
    /**
     *@author YB
     *@version 2019年3月16日下午3:13:05    
     */
    /*
     * 日志记录器工厂接口,充当抽象工厂角色
     */
    public interface LoggerFactory {
        public Logger createLogger();//抽象工厂方法
    }

    5.数据库日志记录器工厂类 充当具体工厂角色 

    package 工厂方法模式;
    /**
     *@author YB
     *@version 2019年3月16日下午3:14:41    
     */
    /*
     * 数据库日志记录器工厂类 充当具体工厂角色
     */
    public class DatabaseLoggerFactory implements LoggerFactory {
    
        @Override
        public Logger createLogger() {
            // TODO Auto-generated method stub
            //链接数据库 代码略
            
            Logger logger=new Databaselogger();//创建数据库日志记录器对象
            
            //初始化数据库日志记录器 代码略
            
            return logger;
            
        }
    
    }

     6.文件日志记录器工厂类 充当具体工厂角色

    package 工厂方法模式;
    /**
     *@author YB
     *@version 2019年3月16日下午3:16:57    
     */
    /*
     * 文件日志记录器工厂类 充当具体工厂角色
     */
    public class FileLoggerFactory implements LoggerFactory{
    
        @Override
        public Logger createLogger() {
            // TODO Auto-generated method stub
            Logger logger=new FileLogger();//创建文件日志记录器对象
            
            //创建文件 代码略
            
            return logger;
        }
    
    }

    7.客户端 

    package 工厂方法模式;
    /**
     *@author YB
     *@version 2019年3月16日下午3:20:06    
     */
    public class Client {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            LoggerFactory loggerFactory;
            Logger logger;
            
            //loggerFactory=new FileLoggerFactory();
            loggerFactory=(LoggerFactory)XMLUtil.getBean();//引入配置文件和反射机制
            logger=loggerFactory.createLogger();
            
            logger.writelog();
            
        }
    
    }

    8.XMLUtil工具类  

    package 工厂方法模式;
    
    import java.io.*;
    
    import javax.swing.text.Document;
    import javax.xml.parsers.*;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.soap.Node;
    import org.w3c.dom.*;
    
    import org.w3c.dom.NodeList;
    
    /**
     *@author YB
     *@version 2019年3月15日下午7:08:17    
     */
    public class XMLUtil {
        //该方法用于从XML配置文件中提取图表类型,并返回类型名
        public static Object getBean() {
            try {
                //创建文档对象
                DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();
                DocumentBuilder builder=dFactory.newDocumentBuilder();
                org.w3c.dom.Document doc;
                doc=builder.parse(new File("src//工厂方法模式//config.xml"));
                
                //获取包含图表类型的文本节点
                NodeList nlList= ((org.w3c.dom.Document) doc).getElementsByTagName("className");
                org.w3c.dom.Node classNode=nlList.item(0).getFirstChild();
                String cName=classNode.getNodeValue();
                
                //通过类名生成实例对象并返回
                Class<?> c=Class.forName(cName);
                Object obj=c.newInstance();
                return obj;
                
            }catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
                return null;
            }
        }
    }

     9.XML配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <config>
    <className>工厂方法模式.DatabaseLoggerFactory</className>
    </config>

    抽象工厂方法的重载:

    当然,抽象工厂的方法也是可以重载的,在抽象工厂中声明多个重载的工厂方法,在具体工厂中实现了这些工厂方法,这些工厂方法可以包含不同的业务逻辑,以满足产品对象的多样化创建需求 

    抽象工厂方法的隐藏:

    在具体工厂类中直接调用产品类的业务方法,这样在客户端就没有必要调用工厂方法来创建产品对象了,可以直接使用工厂对象即可调用所建产品对象中的业务方法

     

    工厂方法模式是使用频率最该的设计模式之一!!!

     

    优点:

    1)工厂方法用来创建客户所需产品,同时还向客户隐藏了那种具体产品类将被实例化这一细节,用户只需关心所需产品对应的工厂,无需关心创建细节,甚至无需知道具体产品的类名

    2)基于工厂角色和产品角色的多态性设计是工厂方法模式的关键,他能够让工厂自主确定创建何种产品对象,而如何创建这个对象的细节完全封装在具体工厂的内部,工厂方法模式之所以被称为多态工厂模式,正是因为所有的具体工厂都有同一抽象父类工厂

    3)在系统中加入新产品时无需修改抽象工厂和抽象产品提供的接口,无需修改客户端,也无需修改其他具体过程和具体产品,而只要添加一个抽象工厂和抽象产品即可,这样系统的可扩展性将变得非常好,完全符合开闭原则

     缺点:

    1)添加新产品时需要编写新的具体产品类还有对应的具体工厂类,系统中类的个数会增加,一定程度上增加了系统复杂度或额外开销

    2)引入了抽象层,增加了系统的抽象性和理解难度

     

    代码下载:链接:https://share.weiyun.com/5YH0BLz 密码:n8psgd

     

     

     

     

  • 相关阅读:
    pyhton 线程锁
    python 守护线程
    python 线程
    python 判断文件的字符编码
    python 进程管道
    python 进程池
    webpack学习(一)起步安装
    最近特别喜欢的一首歌
    你真的了解回流和重绘吗?
    你了解SEO中的时效性吗?
  • 原文地址:https://www.cnblogs.com/yinbiao/p/10542384.html
Copyright © 2011-2022 走看看