简单工厂模式
设计模式 简单工厂+工厂方法+抽象工厂
简单工厂
简单工厂的优缺点:
缺点:①违反了OCP(开放-封闭原则)。(当工厂内增加一个方法创建对象时候,需要在原来的工厂内,添加一个case语句)。修改原来的类,是违反设计原则的。
②增加客户端和工厂类的耦合。
优点:①去除(非降低)客户端和具体产品的耦合。客户端和具体产品中间增加一个工厂类,增加客户端和工厂类的耦合。
②封装工厂类,实现代码多平台的复用性。创建对象的过程被封装成工厂类,可以多平台(控制台+WEB+Winform...手机端)调用这个工厂。
③封装工厂类,创建对象的过程(具体逻辑)包含必要的逻辑,根据客户端的要求,我们可以动态的去创建对象。比如用反射或者new的方式来创建。
“产品”类
public class PersonClass
{
public string Name { get; set; }
public double Height { get; set; }
}
class WhitePerClass : PersonClass
{
}
class BlackPerClass : PersonClass
{
}
class YellowPerClass : PersonClass
{
}
“工厂”类:
public static class ClassFactory
{
public static PersonClass CreateObject(string str)
{
PersonClass perClass = null;
//也可以用反射等逻辑来创建对象。客户端调用时,是管不到我怎么样创建对象的。这是封装的好处之一。
switch (str)
{
case "white":
perClass = new WhitePerClass();
break;
case "black":
perClass = new BlackPerClass();
break;
case "yellow":
perClass = new YellowPerClass();
break;
}
return perClass;
}
}
}
“客户端”:
static void Main(string[] args)
{
//PersonClass perWhite = new WhitePerClass();//虽然“产品”类PersonClass,采用了面向高层的方法,不用工厂创建对象,还是有一定的耦合。
PersonClass perClass = null;
perClass = ClassFactory.CreateObject("white");
perClass.Name = "小白";
perClass.Height = 1.7;
Console.WriteLine(perClass.Name + perClass.Height);
perClass = ClassFactory.CreateObject("black");
perClass.Name = "小黑";
perClass.Height = 2.1;
Console.WriteLine(perClass.Name + perClass.Height);
perClass = ClassFactory.CreateObject("yellow");
perClass.Name = "小黄";
perClass.Height = 1.8;
Console.WriteLine(perClass.Name + perClass.Height);
Console.Read();
}
结果:

再述简单工厂:
产品本身采用了多态。可以new一个产品出来,这样本身降低了客户端和“产品”的耦合,但是未去除耦合。由工厂进一步去除耦合。
缺点:当增加一个产品时,需要在工厂添加一个case语句,修改了原来工厂类。违反了OCP开放封闭原则。
总结简单工厂:
给工厂传一个字符串,返回一个对象。创建逻辑各式各样。
产品树(产品等级)+产品族
都是指的产品。根据品牌和生产厂家分类。
产品树(产品等级):针对产品。指一个产品:品牌不同。
①车(产品):宝马车,奥迪车,奥拓车。
②数据库(产品):MS-SQL,ORACLE,ACCESS,DB2,MongoDB
产品族:针对工厂。一个工厂,产各种产品,各种产品统称一“族”。
①宝马(工厂)生产:宝马自行车,宝马三轮车0.0,宝马的其他产品,衣服,鞋子,宝箱等等。都是一族
②MS-SQL(工厂)生产: user表,department表,role表

工厂方法
特点:只处理一个产品树。可以理解为,只对一张表处理。也是和下面的抽象工厂区别的地方
优点:就是解决简单工厂的缺点(违反了OCP)。和抽象工厂一样,提高程序的扩展性,可以改数据库。增加对应数据库工厂。
缺点:不能增加一个“产品”,只能增加一个工厂,实现了换数据库的功能。但只能处理一个表。若增加一个表就是抽象工厂了。
类图:

个人总结:我们平时用到了工厂模式,一般属于简单工厂或者抽象工厂,因为可以对多个表处理。
抽象工厂:
优点:去除了简单工厂的违反OCP原则,通过添加子类,而不是改变原来类。来增加”产品“。
缺点:每增加一个产品:需要添加一个产品接口+sql产品+oracle产品,还要增加工厂接口+sql工厂+oracle工厂的一个方法。
“产品“类
用户:
interface IUserDal
{
void CRUD();
}
class SqlUserDal : IUserDal
{
public void CRUD()
{
Console.WriteLine("sql数据库User的CRUD");
}
}
class OracleUserDal : IUserDal
{
public void CRUD()
{
Console.WriteLine("Oracle数据库User的CRUD");
}
}
部门:
interface IDepartmentDal
{
void CRUD();
}
class SqlDepartmentDal : IDepartmentDal
{
public void CRUD()
{
Console.WriteLine("sql数据库Department的CRUD");
}
}
class OracleDepartmentDal : IDepartmentDal
{
public void CRUD()
{
Console.WriteLine("Oracle数据库Department的CRUD");
}
}
”工厂“类
interface IFactory
{
IUserDal CreateUserDal();
IDepartmentDal CreateDepartmentDal();
}
class SqlFactory : IFactory
{
public IUserDal CreateUserDal()
{
return new SqlUserDal();
}
public IDepartmentDal CreateDepartmentDal()
{
return new SqlDepartmentDal();
}
}
class OracleFactory : IFactory
{
public IUserDal CreateUserDal()
{
return new OracleUserDal();
}
public IDepartmentDal CreateDepartmentDal()
{
return new OracleDepartmentDal();
}
}
客户端:
static void Main(string[] args)
{
//创建Sql对应dal
SqlFactory sqlFactory=new SqlFactory();
IUserDal sqlUserDal = sqlFactory.CreateUserDal();
sqlUserDal.CRUD();
IDepartmentDal sqlDeparmentDal = sqlFactory.CreateDepartmentDal();
sqlDeparmentDal.CRUD();
//换数据库了,需要创建Oracle对应Dal
OracleFactory oracleFactory = new OracleFactory();
IUserDal oracleUserDal = oracleFactory.CreateUserDal();
oracleUserDal.CRUD();
IDepartmentDal oracleDeparmentDal = oracleFactory.CreateDepartmentDal();
oracleDeparmentDal.CRUD();
Console.Read();
}
结果:

总结:
①理解产品族和产品树(产品等级),方便记忆类图。
②知道工厂方法和抽象工厂的区别
③工厂方法和抽象工厂改善了简单工厂的缺点(违反ocp),带来的缺点是什么。
为了改变抽象工厂增加一个”产品“,带来的繁琐代码,你想到怎么改进了吗?


浙公网安备 33010602011771号