C#设计模式 —— 工厂模式
。 工厂模式同样是项目中最常用的设计模式,工厂模式中又分为简单工厂,工厂方法,抽象工厂。下面我们由简单的开始逐一介绍。
1.简单工厂模式
简单工厂又被称为静态工厂,在设计模式中属于创建型模式。主要解决的问题是封装了实例化的过程,通过传入参数来获不同实例。下面我们举一个项目中可能会用到的例子。
假设我们程序的数据保存在几个不同的数据库中,有MySql,SQLServer和MongoDB。数据库都有增删改查的操作,我们就声明一个接口定义这些操作。
public interface IDatabase
{
void Insert();
void Delete();
}
然后我们让三个数据库类分别实现这个接口。
public class SqlServer : IDatabase
{
public void Delete()
{
Console.WriteLine("delete data from sqlserver");
} public void Insert()
{
Console.WriteLine("insert data to sqlserver");
}
} public class MySql : IDatabase
{
public void Delete()
{
Console.WriteLine("delete data from mysql");
} public void Insert()
{
Console.WriteLine("insert data to mysql");
}
} public class MongoDB : IDatabase
{
public void Delete()
{
Console.WriteLine("delete data from mongoDb");
} public void Insert()
{
Console.WriteLine("insert data to mongoDb");
}
}
之后我们再声明一个工厂类,这个类中的静态方法可以根据传入不同的参数来创建不同的实例。
public static class DatabaseFactory
{
public static IDatabase CreateDatabase(string dbType)
{
IDatabase db = null; switch (dbType)
{
case "MySql":
db = new MySql();
break;
case "SqlServer":
db = new SqlServer();
break;
case "MongoDB":
db = new MongoDB();
break;
default:
break;
} return db;
}
}
最后我们再Main函数里声明三个接口,然后给工厂类传入不同的参数来创建三个不同的实例,再分别调用接口中声明的方法。
static void Main(string[] args)
{
IDatabase db1 = DatabaseFactory.CreateDatabase("MySql");
db1.Insert();
db1.Delete(); IDatabase db2 = DatabaseFactory.CreateDatabase("SqlServer");
db2.Insert();
db2.Delete(); IDatabase db3 = DatabaseFactory.CreateDatabase("MongoDB");
db3.Insert();
db3.Delete();
}
来看一些控制台的输出:

这就是简单工厂模式。
我们可以看到简单工厂模式的优点:
1.拓展性好,如果这时候我们又添加了一个Oracle数据库,只需要再添加一个新的类并实现IDatabase这个这个接口就行了。
2.我们只需要关注接口中的方法,不需要关注具体类的实现。
缺点:只适用于工厂需要创建比较少的具体类这样的情况。如果具体类多,代码的复杂程度会增加。
2.工厂模式
工厂模式在简单工厂模式的基础上进行了更加全面的面向对象封装,可以让我们不要单独的工厂方法就能创建出具体的实例。做法就是为每一个具体的类创建单独的工厂。接下来我们对刚刚几个类稍加改造。
首先发DatabaseFactory修改成一个接口,接口中定义一个用来创建实例的方法。
interface IDatabaseFactory
{
IDatabase CreateDatabase();
}
然后我们然后我们为每个具体类单独创建一个工厂类,工厂类实现刚刚定义的接口。
public class MongoDbFactory : IDatabaseFactory
{
public IDatabase CreateDatabase()
{
return new MongoDB();
}
} public class MySqlFactory : IDatabaseFactory
{
public IDatabase CreateDatabase()
{
return new MySql();
}
} public class SqlServerFactory : IDatabaseFactory
{
public IDatabase CreateDatabase()
{
return new SqlServer();
}
}
最后我们在main函数中创建工厂的实例。
static void Main(string[] args)
{
IDatabaseFactory dbFactory1 = new MySqlFactory();
IDatabase db1 = dbFactory1.CreateDatabase();
db1.Insert();
db1.Delete(); IDatabaseFactory dbFactory2 = new SqlServerFactory();
IDatabase db2 = dbFactory1.CreateDatabase();
db2.Insert();
db2.Delete(); IDatabaseFactory dbFactory3 = new MongoDbFactory();
IDatabase db3 = dbFactory3.CreateDatabase();
db3.Insert();
db3.Delete();
}
结果输出是和刚刚一模一样的。工厂模式的好处便是它符合开闭原则(对扩展开放,对修改封闭)。在刚刚的简单工厂模式中,如果我们扩展一个新的类,除了添加一个新的类之外,我们还需要去修改CrateDatabase(string dbType)这个方法,这是违反开闭原则的。在工厂模式中我们就不需要修改CreateDatabase这个方法,只需要实现工厂类这个接口便能完场扩展。缺点便是我们需要写更多的代码。
3.抽象工厂模式
有了前面工厂模式的铺垫,抽象工厂应该不难理解吧。我看到过很多的博客都写着很多概念,什么产品层级,产品族,抽象产品等等,感觉不是特别容易理解。我的理解是这样的:把多个不同的工厂再抽象出来,再用一个抽象工厂(超级工厂)来创建这些工厂。也就是说抽象工厂是工厂的工厂。为了说明这个模式我想出了一个例子(其实我在工作中没有遇到过使用抽象工厂的例子):
操作系统有Windows操作系统,Linux操作系统。每个操作系统都可以启动关闭。于是我们就创建一个操作系统工厂,用来创建(安装)这些操作系统,方法和上面的创建数据库工厂是一样的。
// 操作系统具有的操作
public interface IOpSystem
{
void Start();
void Shutdown();
} // 操作系统工厂
public interface IOpSystemFactory
{
IOpSystem InstallSystem();
} // windows操作系统
public class WindowsSystem : IOpSystem
{
public void Shutdown()
{
Console.WriteLine("windows shutdown");
} public void Start()
{
Console.WriteLine("windows start");
}
} // linux操作系统
public class LinuxSystem : IOpSystem
{
public void Shutdown()
{
Console.WriteLine("linux shutdown");
} public void Start()
{
Console.WriteLine("linux start");
}
} // windows操作系统工厂,用来创建windows系统实例
public class WindowsFactory : IOpSystemFactory
{
public IOpSystem InstallSystem()
{
return new WindowsSystem();
}
} // linux操作系统工厂,用来创建linux系统实例
public class LinuxFactory : IOpSystemFactory
{
public IOpSystem InstallSystem()
{
return new LinuxSystem();
}
}
我们可以看到操作系统工厂和数据库工厂是完全两个不同的工厂。假设一台服务器上需要安装操作系统和数据库,我们便可以用一个超级工厂来把这两个不同的工厂抽象出来。
public interface ISuperFactory
{
IDatabaseFactory InstallDB();
IOpSystemFactory InstallOpSystem();
}
然后我们定义一个具体的服务器类来实现这个超级工厂,在接口的实现中我们让这个服务器类安装windows system和mysql db。
public class ServerWithWindowsAndMySql : ISuperFactory
{
public IDatabaseFactory InstallDB()
{
return new MySqlFactory();
} public IOpSystemFactory InstallOpSystem()
{
return new WindowsFactory();
}
}
最后在Main函数中调用看看。
static void Main(string[] args)
{
ISuperFactory server1 = new ServerWithWindowsAndMySql();
server1.InstallDB().CreateDatabase().Delete();
server1.InstallDB().CreateDatabase().Insert();
server1.InstallOpSystem().InstallSystem().Start();
server1.InstallOpSystem().InstallSystem().Shutdown();
}
下面是运行结果。

我们可以看到实现了超级工厂的服务器类同时拥有了创建数据库和安装操作系统的功能。这就是抽象工厂的用法。我们来看看抽象工厂的优缺点。优点:
1.实现了不同工厂之间的解耦。
缺点:
1.代码量成倍的增加
2.抽象工厂并不符合开闭原则。如果这个时候我们需要在超级工厂中添加一个新的工厂,那么具体类也必须要作出修改。
4.总结
工厂模式同样是设计模式中比较常用而且比较容易理解(抽象工厂除外)的设计模式。同时也能加深我们对面向对象中“多态”这个概念的理解:我们只需要关注接口中方法的声明,不用知道具体类有什么方法方法如何实现。换句话说我们只需要声明了一个接口,便可以直接调用接口的方法,当然前提是接口必须由实现该接口的具体类来实例化。同时我们在工作中也必须对设计模式的使用稍加思考,只有我们需要去使用这个设计模式的时候才去使用,如果我们为了使用设计模式而去使用设计模式,我们反而会得到糟糕的效果。
C#设计模式 —— 工厂模式的更多相关文章
- .NET设计模式: 工厂模式
.NET设计模式: 工厂模式(转) 转自:http://www.cnblogs.com/bit-sand/archive/2008/01/25/1053207.html .NET设计模式(1): ...
- 【设计模式】Java设计模式 -工厂模式
[设计模式]Java设计模式 -工厂模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! 目 ...
- [Head First设计模式]饺子馆(冬至)中的设计模式——工厂模式
系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...
- javascript 设计模式-----工厂模式
所谓的工厂模式,顾名思义就是成批量地生产模式.它的核心作用也是和现实中的工厂一样利用重复的代码最大化地产生效益.在javascript中,它常常用来生产许许多多相同的实例对象,在代码上做到最大的利用. ...
- JavaScript设计模式——工厂模式
工厂模式:是一种实现“工厂”概念的面上对象设计模式.实质是定义一个创建对象的接口,但是让实现这个接口的类来决定实例化哪个类.工厂方法让类的实例化推迟到子类中进行.创建一个对象常常需要复杂的过程,所以不 ...
- 10.Java设计模式 工厂模式,单例模式
Java 之工厂方法和抽象工厂模式 1. 概念 工厂方法:一抽象产品类派生出多个具体产品类:一抽象工厂类派生出多个具体工厂类:每个具体工厂类只能创建一个具体产品类的实例. 即定义一个创建对象的接口(即 ...
- 学习:java设计模式—工厂模式
一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类: 1)简单工厂模式(Simple Facto ...
- 设计模式——工厂模式 (C++实现)
软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径.设计模式中运用了面向对象编程语言的重要特性:封装.继承.多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累. ...
- Java设计模式---工厂模式(简单工厂、工厂方法、抽象工厂)
工厂模式:主要用来实例化有共同接口的类,工厂模式可以动态决定应该实例化那一个类.工厂模式的形态工厂模式主要用一下几种形态:1:简单工厂(Simple Factory).2:工厂方法(Factory M ...
- 设计模式——工厂模式(Factory)
要想正确理解设计模式,首先必须明白它是为了解决什么问题而提出来的. 设计模式学习笔记 --Shulin 转载请注明出处:http://blog.csdn.net/zhshulin 1.概念 工厂模式定 ...
随机推荐
- css属性之float
0.float与margin 两个相邻的浮动元素,当第一个浮动元素(不论是左浮动还是右浮动)的宽度为100%时,第二个浮动元素会被挤到下面,通过添加负margin-right值(绝对值最少等于它自身的 ...
- jQuery的attr()与prop()的区别
jQuery的attr()与prop()都是用于获取与设置属性的,但它们又各有不同. attr()一般是用于设置默认值,prop()一般是用于设置属性值,即对于像“diabled”,"che ...
- zTree 学习笔记之(一)
zTree 学习笔记之(一) 简介 zTree 是一个依靠 jQuery 实现的多功能 “树插件”.优异的性能.灵活的配置.多种功能的组合是 zTree 最大优点. 到底有哪些具体的优点,可以参见官网 ...
- Android解析WindowManagerService(二)WMS的重要成员和Window的添加过程
前言 在本系列的上一篇文章中,我们学习了WMS的诞生,WMS被创建后,它的重要的成员有哪些?Window添加过程的WMS部分做了什么呢?这篇文章会给你解答. 1.WMS的重要成员 所谓WMS的重要成员 ...
- 《ArcGIS Runtime SDK for Android开发笔记》——(4)、基于Android Studio构建ArcGIS Android开发环境
1.前言 2015年1月15日,发布ArcGIS Runtime SDK for Android v10.2.5版本.从该版本开始默认支持android studio开发环境,示例代码的默认开发环境也 ...
- Appium元素定位(uiautomatorviewer)
一.uiautomatorviewer元素定位 1.adroid-sdk的安装目录tools下有1个自带的工具uiautomatorviewer,打开后,如下所示: 点击后,如图所示: 步骤: a.链 ...
- selenium元素定位方法
一.如何找到页面元素 Webdriver的findElement方法可以用来找到页面的某个元素,最常用的方法是用id和name查找.下面介绍几种比较常用的方法. 1.1By ID 假设页面写成这样:i ...
- No enum constant org.apache.ibatis.type.JdbcType.Integer
同事今天在用mybatis查询时候,报了上面这个问题.上网查了下,原来是mybatis封装类型的问题.原因是在resultMap中jdbcType写为了Integer,但是在MyBatis中没有这个数 ...
- Project Euler 44: Find the smallest pair of pentagonal numbers whose sum and difference is pentagonal.
In Problem 42 we dealt with triangular problems, in Problem 44 of Project Euler we deal with pentago ...
- Python学习---网络编程 1217【all】
OSI七层模型: 物理层, 数据链路层, 网络层,传输层,会话层,表达层,应用层 应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等 传输层:TCP,UDP 网络层:I ...