











前几讲链接:
1、设计模式杂谈:开头篇
2、设计模式杂谈:创建型模式之工厂方法(Factory Method)
在上一讲“设计模式杂谈:创建型模式之工厂方法(Factory Method)”中,已经通过一个案例对工厂方法进行了讲述。也有不少朋友看了提出了一些建议,确实,在上一讲中,只是简单的讲了工厂方法的用法,但有些地方并不适合于实际应用。主要是最后的创建工厂方法实例时,我把这个工厂方法的创建与该工厂方法创建的具体对象,以及它的执行都放在一起,显然这种做法是错误的,如果这样做的话,还不如直接创建要执行的具体对象,没有必要再搞一个工厂方法进去,有点多此一举的味道,就好象一个包装盒,外面又包了一层,但却并没有起到一定的作用。在这一讲中,在讲单件模式之前,我先对上一讲中的问题进行一些必要的忧化,可能这样会更符合实际的应用。
现在我们再回头看一下上一讲中最后实现的一段代码:
1
double basicSalary;
2
double result;
3
4
basicSalary = Convert.ToDouble(txtBasicSalary.Text.Trim());
5
6
IBLL.IFactory factory = new Factory.ChineseFactory();
7
IBLL.ISalary salary = factory.CreateSalary();
8
9
result = salary.Calculate(basicSalary);
10
11
lbSalary.Text = result.ToString();
我们现在可以把这个系统想的复杂一些,如果说工资的计算在很多模块里都要用到,按现在的这种做法,则必须在要用到的模块里,重新通过IBLL.IFactory factory = new Factory.ChineseFactory();这个来创建工厂方法,再通过这个工厂来创建相应的ISalary对象,那么一旦需求改了,需要换成美国公司的,那么必须修改每一个模块,这样做的话,那么这个工厂方法真是一个鸡肋了,还不如不要了,可能更方便。所以首选必须把具体工厂的创建放在一个单独的地方,这样就可以统一管理,一旦需求改了,只要改变该地方就可以了。
好,下面我就就再创建了个FactoryUtility.cs文件,具体代码:
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Configuration;
5
using System.Reflection;
6
7
namespace DesignPattern.Common
8
{
9
public class FactoryUtility
10
{
11
public IBLL.IFactory GetFactory()
12
{
13
IBLL.IFactory factory = new Factory.ChineseFactory();
14
15
return factory;
16
}
17
18
}
19
}
20
1
double basicSalary;
2
double result;
3
4
basicSalary = Convert.ToDouble(txtBasicSalary.Text.Trim());
5
6
IBLL.IFactory factory = new FactoryUtility().GetFactory();
7
IBLL.ISalary salary = factory.CreateSalary();
8
9
result = salary.Calculate(basicSalary);
10
11
lbSalary.Text = result.ToString();
1
<?xml version="1.0" encoding="utf-8" ?>
2
<configuration>
3
<appSettings>
4
<add key="FactoryName" value="DesignPattern.Factory.ChineseFactory"/>
5
</appSettings>
6
</configuration>
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Configuration;
5
using System.Reflection;
6
7
namespace DesignPattern.Common
8
{
9
public class FactoryUtility
10
{
11
public IBLL.IFactory GetFactory()
12
{
13
string factoryName = ConfigurationSettings.AppSettings["FactoryName"];
14
factory = (IBLL.IFactory)Assembly.Load("Salary").CreateInstance(factoryName);
15
16
return factory;
17
}
18
19
}
20
}
21
这时我们再来看看,如果要满足美国企业的时候,我们再不需要去改变程序代码,只要修改配置文件App.Config即可:
1
<?xml version="1.0" encoding="utf-8" ?>
2
<configuration>
3
<appSettings>
4
<add key="FactoryName" value="DesignPattern.Factory.AmericanFactory"/>
5
</appSettings>
6
</configuration>
当然,这里对于客户来说还不是很直观,这个可以再进一步的去忧化配置文件,这里就不再讲述了。
到此为上,经过上述的一系列优化后,已经变得很灵活了,能基本适应美国公司和中国公司的需求。
好,我们现在转到正题(呵,好象也不是什么正题了)。下面我们来看一下创建型设计模式的单件模式,其实这个模式是比较特殊的一种,也是最好理解的。顾名思义,就是只创建一个实例,这在一些特定的场合是非常有用的,比如说最常见的,就是我们进行数据库操作时必须要创建的一个sqlConnection对象,由于数据库连接都是通过这个对象来操作的,所以我们没有必要创建该对象的多个实例,只创建一个就可以了,这样即节省资源又可以避免一些异常的发生,更容易控制。
其实,在程序开发中,我们已经在不知不觉的使用单件模式了。最简单的就是使用static关键字定义对象,其实这就是一种单件模式了。常见的单件模式的样式如下代码所示:
1
private static object ob;
2
public static object OB
3
{
4
get
5
{
6
if (ob == null)
7
{
8
9
ob = new object();
10
11
}
12
return ob;
13
}
14
}
也可以对该单件模式进行改进,如对于多线程应用程序,我们就应该在上面加一把锁,以防该对象被多次创建:
private static readonly object pad = new object();
private static object ob;
public static object OB
{
get
{
if(ob == null)
{
lock (pad)
{
if (ob == null)
{
ob = new object();
}
}
}
return ob;
}
}
如果有些朋友想更多的了解单件模式的话,请看TerryLee写的设计模式系列“ .NET设计模式系列 ”。
现在我们再回头看看原来的程序,一旦部署后,那么其实这个工厂方法也就确定,由于我们真正要用到的实现方法对象是由该工厂方法来创建的,所以该工厂方法没有必要被多次实例化,在整个系统中我们只需要一个实例久可以了,由这个工厂实例我们就可以创建在计算工资时用到的对象,因此在这里我们就可以用到单件模式了。
再一次修改FactoryUtility.cs文件,得到新的代码:
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Configuration;
5
using System.Reflection;
6
7
namespace DesignPattern.Common
8
{
9
public class FactoryUtility
10
{
11
private static readonly object ton = new object();
12
private static IBLL.IFactory factory = null;
13
14
public static IBLL.IFactory Factory
15
{
16
get
17
{
18
if (factory == null)
19
{
20
lock (ton)
21
{
22
if (factory == null)
23
{
24
25
string factoryName = ConfigurationSettings.AppSettings["FactoryName"];
26
factory = (IBLL.IFactory)Assembly.Load("Salary").CreateInstance(factoryName);
27
28
}
29
}
30
}
31
return factory;
32
}
33
}
34
}
35
}
36
最后,我们再来看一下,最后实现代码:
1
double basicSalary;
2
double result;
3
4
basicSalary = Convert.ToDouble(txtBasicSalary.Text.Trim());
5
6
7
IBLL.ISalary salary = FactoryUtility.Factory.CreateSalary();
8
9
result = salary.Calculate(basicSalary);
10
11
lbSalary.Text = result.ToString();
好了,这篇就讲到这里了,希望各位朋友能看得懂。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。