前言
简略工厂模式属于创立型模式之一,是最常见的设计模式,利用也相当宽泛。创立型模式通过让对象的创立和应用拆散,使得开发人员在应用对象的时候无需关怀对象的创立细节,从而升高零碎的耦合度。
创立型模式
该类模式在开发过程中的应用十分频繁,创立型模式关注对象的创立过程,对类的实例化进行了形象,将模块中对象的创立和应用拆散,对外暗藏了对象的创立细节。
简略工厂模式
概念
定义一个工厂类并提供一个办法,工厂办法能够依据参数的不同返回不同的实例,被创立的实例通常都具备雷同的父类。因为简略工厂模式中提供的办法通常是静态方法,所以该模式又能够成为动态工厂办法模式。
设计思维
将须要创立的各种不同对象的相干代码封装到不同类中,这些类称为具体的产品类,再形象和提取它们公共的代码封装在一个形象产品类中,每一个具体产品类都继承自形象产品类 (属于其子类)。而后提供一个工厂类用于创立各种不同的产品,在工厂类中提供一个创立产品的办法,这个办法反对传参,依据传入的参数不同创立不同的具体产品对象。使用者只须要调用工厂办法并传入对应的参数即可失去绝对的产品对象。
构造与实现
结构图
由结构图可知,简略工厂模式蕴含 3 个角色,别离如下:
- Factory(工厂):工厂类,简略工厂模式的外围,负责实现创立所有产品的外部逻辑。工厂类中提供的静态方法能够间接被内部调用,并且返回形象产品类型 Product
- Product(形象产品):它是工厂类所创立的所有产品的基类,封装了各种产品的公共办法
- ProductA&ProductB(具体产品角色):是简略工厂模式须要创立的指标,每一个具体产品都继承自 Product
简略工厂模式的实现
- 将所有产品的共性移至形象产品中
// 形象基类
abstract class Product
{public void SameMethod()
{
// 所有产品的公共办法
Console.WriteLine("所有产品的公共办法");
}
// 差异化行为
public abstract void DiffMethod();}
- 创立具体产品类,并实现形象办法中申明的形象办法,不同的产品能够有依据需要有不同的实现
// 产品 A
class ProductA : Product
{public override void DiffMethod()
{
// 这里实现产品 A 的业务逻辑
Console.WriteLine("这里实现产品 A 的业务逻辑");
}
}
- 外围工厂类
// 工厂类
class Factory
{
// 静态方法
public static Product GetProduct(string type)
{if (type.Equals("A"))
return new ProductA();
else if (type.Equals("B"))
return new ProductB();
return null;
}
}
- 应用
static void Main()
{var product = Factory.GetProduct("A");
product.SameMethod();
product.DiffMethod();
Console.ReadKey();}
- 运行后果
能够发现,如果须要创立其它的具体产品对象,必须批改获取对象时传入的参数才能够实现,且代码须要从新编译,这违反了开闭准则。能够通过读取 XML 配置解决该问题,批改代码如下:
- 将须要创立的产品类型保留到配置文件 App.config 中
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<appSettings>
<add key="productType" value="A"/>
</appSettings>
</configuration>
- 批改代码如下
static void Main()
{
// 读取配置文件
var pType = ConfigurationManager.AppSettings["productType"];
var product = Factory.GetProduct(pType);
product.SameMethod();
product.DiffMethod();
Console.ReadKey();}
- 运行后果
批改后的代码应用命名空间 System.Configuration 中 ConfigurationManager 类的 AppSettings 属性获取存储在配置文件中的 productType,在源码中不蕴含任何写死的产品类型,如果须要更换创立的具体产品对象,只需批改配置文件中对应的数据即可,无需批改代码,无需从新编译,合乎开闭准则。
对象的职责
与一个对象相干的职责通常可分为 3 种类型:创建对象、应用对象、对象自身的职责。如果一个类中既蕴含创建对象又蕴含应用对象,值得注意,这样的设计往往会导致的问题是,如果后续需要变动,须要创立形象产品的另外一个子类,就必须批改代码。最广泛的办法就是将对象的创立移入工厂中实现,从而达到对象的创立与应用拆散,代码解耦。
两个类之间的关系应该尽量简略,如类 A 类 B,应是 A 创立 B,或者 A 应用 B,而不能 A 既创立 B 的同时又应用 B,让零碎更加合乎繁多职责有利于性能的复用与零碎的保护。
是否须要为每一个类都创立一个工厂类?
不须要,如果类很简略,结构过程也不简单,且不存在太多的变动,便不须要专门为其提供工厂类,间接创立应用即可,否则将会导致工厂泛滥,减少零碎的复杂度,成果反而事与愿违了。
简略工厂模式的优缺点
长处
- 能够防止实例化对象的代码在每个应用对象的类中到处都是,因为实例化对象不总是调用构造函数即可,有时还得设置参数,如果这些代码散落在每个创建对象的类中,必然会导致大量的反复代码,而这些类仅仅只须要取得创立好的对象加以应用即可,齐全没必要承当创建对象的职责。
- 对于有多个构造函数的类,引入工厂能够减少代码可读性,如下:
class Rectangle
{
// 创立长方形
public Rectangle(int w, int h) { }
// 创立正方形
public Rectangle(int w) {}}
class RectangleFactory
{
// 创立长方形
public static Rectangle CreateRectangle(int w, int h)
{return new Rectangle(w, h);
}
// 创立正方形
public static Rectangle CreateSquare(int w)
{return new Rectangle(w);
}
}
- 实现了对象创立和应用的拆散,通过引入配置文件后还能够在不批改客户端代码更换具体对象,减少了零碎的灵活性。
毛病
- 工厂类中蕴含所有具体产品的创立逻辑,职责过重
- 应用简略工厂模式会减少零碎中类的个数,减少零碎复杂度和了解难度
- 每减少新的对象必须批改工厂类中的逻辑,零碎扩大艰难
- 简略工厂模式因为应用了静态方法,将无奈针对父类工厂编程,在运行时应用工厂子类笼罩父类,工厂类得不到很好的扩大
什么时候适宜应用简略工厂模式?
- 工厂类负责创立的对象较少
- 开发者只需关怀传入工厂的参数,而无需关怀对象的创立过程