抽象工厂的应用

抽象工厂的应用

 本文是描述了自己对设计模式的工厂的了解.肯定有错误和不足的地方,希望大家能给予支持和建议.

1.问题的引出

    在前面的Post中,我描述了.NET的反射在软件设计中的应用.当这篇Post发表之后,有人认为用工厂来实现更合理一些。

    在这篇Post里,描述的是根据某些条件如何动态的创建一个类的实例(这些条件最常见的是从应用程序的配置文件里去读取,比如Web项目,你可以从.config文件里去读取),比如有一个类名为SqlDataProvider,我们就可以使用”SqlDataProvider”字符串来构造一个SqlDataProvider实例。这就用到了反射,具体实现方法,参看这篇Post。

 为什么要这样去做呢?其中我提到了是为了更好的扩展应用程序,可以使应用程序更加灵活,比如哪天我得数据库不是 Mircrosoft SQL Server,而是Oracle,怎么办呢?很简单,你只需修改一下你的配置文件,写为“OracleDataProvider”即可,当然,你也必须在你的程序里实现这个类了。但是不管是SqlDataProvider,还是OracleDataProvider,都必这篇Post须继承自DataProvider这个抽象类。

这里用的是反射,那还有没有其他解决方案呢?

2 问题解决方案的提出

   显然,解决方案是有都的,并且相当经典。 正如这篇Post的评论一样,可以采用工厂类解决。所以这里我们就用工厂来解决,并且我也更倾向于这一种方法。

  首先,这种工厂真正称为Abstract Factory,它是一种设计模式(Design pattern),是创建模式(Creational Pattern)的一种。既然是创建模式,首先应该明白什么是创建模式?请看GOF的原文(原书英文版,第81页):

 Creational design patterns abstract the instantiation process. They help make a system independent of how its objects are created, composed, or represented. A class creational pattern uses inheritance to vary the class that’s instantiated, whereas an object creational pattern will delegate instantiated to another object.

 了解了创建模式后,让我们了解Abstract Factory,还是利用GOF的原文解释吧。第87页:
  Intent

 Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

意思再清楚不过了。如果想得到更多信息,参考GOF的《Design Pattern》一书。

据上所说,我认为它提供了一个接口供创建相关的一组对象等。

结构如下:

%E6%8A%BD%E8%B1%A11.gif 

下面是对应的实例:

%E6%8A%BD%E8%B1%A12.gif 

很明显,结构里的AbstractFactory就是WidgetFactory,ConcreteFactory1就是MotifWidgetFactory,

ConcreteFactory2就是PMWidgetFactory。ConcreteFactory1负责构造Motif的Window,

ConcreteFactory2构造PM的window,所谓各司其职呀。

我想根据上面的图,我们对工厂模式有一个很好的了解了。

3 解决方案的一个实例

  在我们学习.NET时,Microsoft提供了一个实例,那就是在Java世界和现在.NET阵营特有名的PetShop(版本是3.0以上)。在这个版本种,它提供了一DALFactory,不用看代码,就知道它干了一些什么事情。DAL(Data Access Layer,数据访问层),Factory,工厂。好了,我也不多说了。看看一下他的类图吧。

 

 %E6%8A%BD%E8%B1%A13-1.gif

首先我们应该知道,PetShop的数据库既可以是SQLServer,也可以是Oracle,所以才有了SQLServerDAL和OracleDAL。对于Account,在BLL(Business Logic Layer,业务逻辑层)里的Account类调用了DAL工厂的Account,想想DAL工厂是如何工作的。假设我们现在用的是SQL Server,我们肯定会用SQLServerDAL里的Account,而不是Oracle里的。问题这样就来了,如何去创建这个对象呢?在前面提到,我们可以根据应用的程序的配置文件来创建。我们只需要说明我们现在使用的是SQL Server,其相应的是SQLServerDAL即可。仔细阅读一下源代码,发现它确实是这样做的。现在以BLL的Account的SignIn方法为例,给出PetShop的源代码:
 BLL的Account的SignIn();


          public AccountInfo SignIn(string userId, string password) {

 

                                    // Validate input

                                    if ((userId.Trim() == string.Empty) || (password.Trim() == string.Empty))

                                                return null;

 

                                    // Get an instance of the account DAL using the DALFactory

                                    IAccount dal = PetShop.DALFactory.Account.Create();

 

                                    // Try to sign in with the given credentials

                                    AccountInfo account = dal.SignIn(userId, password);

 

                                    // Return the account

                                    return account;

                        }


         DALFactory.Account.Create()的源代码:

            public class Account

            {

                        public static PetShop.IDAL.IAccount Create()

                        {                                  

                                    /// Look up the DAL implementation we should be using

                                    string path = System.Configuration.ConfigurationSettings.AppSettings["WebDAL"];

                                    string className = path + ".Account";

 

                                    // Using the evidence given in the config file load the appropriate assembly and class

                                    return (PetShop.IDAL.IAccount) Assembly.Load(path).CreateInstance(className);

                        }

            }

注意

System.Configuration.ConfigurationSettings.AppSettings["WebDAL"];

这行代码,它从配置文件离地到WebDAL的内容,即“PetShop.SQLServerDAL”,所以最后className是PetShop.SQLServerDAL.Account.这样就创建了一个SQLServerDAL的实例,返回的确实IAccount对象,但是根据面向对象原理,最后调用的还是SQLServerDAL.Account.

好了,再给出另外一个实例:

%E6%8A%BD%E8%B1%A14-1.gif 

与上面的类似,我就不再多说了。

4.Post的问题的解决

 了解了上面的原理,再加上PetShop的实例,我想解决上一篇Post的问题就不算太难了。下面给出设计图.

 

%E6%8A%BD%E8%B1%A15-1.gif

5.需解决问题

1) 抽象类(Abstract Class)和接口(Interface)的区别

显然,在设计模式中,抽象是非常重要的,这样就需要用到抽象类和接口,那么这两者有什么联系和区别呢?希望大家可以提出意见和建议.

2)  Abstract Facotry和Factory Method的区别

这两个设计模式之间既有相似之处又有不同之点,希望大家能说出其关系,使我们更加清楚的了解他们,了解设计模式的精髓.

真诚希望大家给出自己的看法.

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.tpcf.cn/news/467417.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一口气搞懂「文件系统」,就靠这 25 张图了

前言不多 BB,直接上「硬菜」。正文文件系统的基本组成 文件系统是操作系统中负责管理持久数据的子系统,说简单点,就是负责把用户的文件存到磁盘硬件中,因为即使计算机断电了,磁盘里的数据并不会丢失,所以可…

linux里没有grub文件,linux – 安装Ubuntu后没有grub菜单,直接启动...

我有两个独立的SSD.其中一个安装了Windows 10 Pro,另一个安装了Ubuntu 14.04.3 LTS.当我的计算机启动时,我没有选择grub菜单来选择我要启动的操作系统,它会直接自动启动到Ubuntu.当将SSD设置为BIOS中引导顺序中的第一个SSD时,我可以启动进入Windows的问题.我有第三个2TB硬盘,我…

Samba远程代码执行漏洞(CVE-2017-7494)复现

简要记录一下Samba远程代码执行漏洞(CVE-2017-7494)环境搭建和利用的过程,献给那些想自己动手搭建环境的朋友。(虽然已过多时) 快捷通道:Docker ~ Samba远程代码执行漏洞(CVE-2017-7494) 演 示:服务器版“永恒之蓝”高危预警 &#xff0…

mac 终端登陆linux,Mac终端自动登录服务器

效果输入命令,选择一个序号登录服务器$ aoel(1) first 192.168.1.1(2) 第二台机器 192.168.1.2配置文件1. 填写服务器信息 computerInfo.ini#ip port user password description192.168.1.1 22 root 123456 first machine192.168.1.2 22 root 123456 第二台机器2. 使…

你说,辽宁输在哪了?

今晚看完了整场比赛,比赛很激烈,有完美的地方,也有不完美的地方看完比赛后,我一个刚从美国回来,现在在凤凰山脚下隔离的同学发消息给我说 「怎么才打三场就拿了总冠军了」?说下比赛整场比赛,辽宁…

[导入]Gemini翻譯為中文時的注意事項

1. 一般檔案 *.aspx, *.ascx 在翻譯為繁體中文或簡體中文後都要儲存為ANSI格式,不可用UTF-8,不然會亂碼,繁體轉簡體也有問題 2. Template中信件的樣版檔案 *.vm ,反而要另存為 UTF-8 格式,不然收到的信會是亂…

linux cocos环境变量,Linux开发cocos2dx程序环境搭建

安装linux系统,ubuntu 14.04 64位linux安装支持软件sudo apt-get updatesudo apt-get install git ssh vim ctags qt-sdk build-essential libx11-dev libxmu-dev libglu1-mesa-dev libgl2ps-dev libxi-dev libglfw-dev libzip-dev libcurl4-gnutls-dev libfontconf…

答应了好久的camera资料

之前是在知识星球上,有好几个同学问了camera的资料,我简单的说了下,也送了些资料,然后微信好友又有人问,我觉得camera这个,应该是要发一次资料了。之前写过的关于camera的文章安卓camera总体框架Camera摄像…

[新功能]删除团队文章

现在团队管理员可以删除团队中的文章。操作方法:在团队管理中,选择“文章管理”,然后可以在列出的文章标题旁点击“移出”,或者手动输入文章地址进行移出。转载于:https://www.cnblogs.com/dudu/archive/2005/05/16/156674.html

第九周学习

20162310林臻 《程序设计与数据结构》第九周学习总结 教材学习内容总结 堆的学习及其方法的应用堆排序利用堆的基本特征对一组元素进行排序 教材学习中的问题和解决过程问题1:堆和二叉树有什么区别呢问题1解决方案:1、堆是一个完全二叉树,并且…

Linux kernel同步机制

在现代操作系统里,同一时间可能有多个内核执行流在执行,因此内核其实像多进程多线程编程一样也需要一些同步机制来同步各执行单元对共享数据的访问,尤其是在多处理器系统上,更需要一些同步机制来同步不同处理器上的执行单元对共享…

linux 文件系统 簇 浪费空间,Linux rm -rf删除文件不释放空间的解决办法

前几天发现在Linux系统下有一个很大的无用文件,于是用rm -rf 删除,然后用df -h查看磁盘空间,发现即使文件被删除了,但文件所占用的空间并未释放,十分疑惑,于是在网上找到了解决方案,即使用lsof …

[Diary]6.10

一大早回闵行,继续奋斗论文。我真是个小巫,不停的自言自语。

linux 特定用户ssh,linux - 如何在登录后将SSH用户限制为一组预定义的命令?

你为什么不写自己的login-shell? 为此使用Bash会非常简单,但您可以使用任何语言。Bash中的示例使用您喜欢的编辑器创建文件;(这可以是任何名称或路径,但应该是&和&&):#!/bin/bashcommands("man" "pwd&…

水晶报表的推模式

在一个多层结构中,水晶报表的使用往往比较繁琐:1、在项目中添加数据集,形成xsd文件2、利用xsd文件,在水晶报表环境中生成报表3、回到.net,添加rpt文件这样做的坏处除了繁琐,就是在UI层直接要访问数据库&…

关于sql和MySQL的语句执行顺序(必看!!!)

ql和mysql执行顺序,发现内部机制是一样的。最大区别是在别名的引用上。 一、sql执行顺序 (1)from (3) join (2) on (4) where (5)group by(开始使用select中的别名,后面的语句中都可以使用)(6) avg,sum.... (7)having (8) select (9) distinct (10) orde…

fedora linux命令,Fedora Linux的一些常用设置和常用命令

1.设置常用路径跳转:alias ubootcd /opt/U-boot-2009.11_tekkaman/U-boot-2009.11_tekkaman/2.samba服务重启命令在更改ip后,或修改samba配置文件后,如果没有重启服务,所作的修改实际上是不会生效的重启网络服务的命令是service network rest…

10大黑客专用的 Linux 操作系统,你了解哪些?

今天列出一些最常用、最受欢迎的Linux发行版来学习黑客和渗透测试。1. Kali LinuxKali Linux是最著名的Linux发行版,用于道德黑客和渗透测试。Kali Linux由Offensive Security开发,之前由BackTrack开发。Kali Linux基于Debian。它带有来自安全和取证各个…

【windows phone】CollectionViewSource的妙用

在windows phone中绑定集合数据的时候,有时候需要分层数据,通常需要以主从试图形式显示。通常的方法是将第二个ListBox(主视图)的数据源绑定到第一个ListBox (从视图)的SelectedItem,或者通过第…

ftp linux包,图文详解Ubuntu搭建Ftp服务器的方法(包成功)

一、今天下午由于课程的要求不得已做了Ubuntu搭建Ftp服务器的实验,但是实验指导书还是N年前的技术,网上搜了一大把,都是模模糊糊的!在百般困难中终于试验成功,特把经验分给大家 希望大家少走弯路!二、详细步…