。
首先请下载开发演示文件,把它解压到一个目录,你可以看到如下的Basic项目。
们编写了一个产品组件,还有一个销售管理组件。不过那个组件会在今后的AOP里再演示了。现看看产品组件,是否很简单:
namespace QPG.Demo.Components


{
using System;


public class Product

{
private int _price;
private int _stocks;

private string _name;

public Product()

{
_name="";
_price=0;
_stocks=0;
Console.WriteLine("call Product()");//用来查看容器是否自动初始化对象

}

public Product(string name,int price,int num)
{
_name=name;
_price=price;
_stocks=num;
Console.WriteLine(string.Format("Product({0},{1},{2})",name,price,num));
}


public virtual string Name
{

get
{return _name;}
}

public virtual int Price
{

get
{return _price;}
}

public virtual int Stocks
{

get
{return _stocks;}
}


public virtual void setPrice(int newPrice)
{
_price=newPrice;
}


public virtual void outStock(int num)
{
int temp=_stocks-num;
if(temp<0) throw new Exception("stock lack!");
_stocks=temp;
}
}
}

打开bin\Debug\config\app_config.xml,这个文件用来配置您自己编写的组件。本例中的配置如下:
<?xml version="1.0" encoding="utf-8" ?>

<configuration>
<components>
<component id="p1" type="QPG.Demo.Components.Product,Basic" lifestyle="Singleton" >
<parameters>
<name>P1</name>
<price>333</price>
<num>33</num>
</parameters>
</component>
<component id="p2" type="QPG.Demo.Components.Product,Basic" lifestyle="Pooled" initialPoolSize="2" maxPoolSize="4" />
<component id="p3" type="QPG.Demo.Components.Product,Basic" lifestyle="Transient" />
</components>
</configuration>

我们配置了三个Product对象:
p1就只会存在一个,并且不会被容器释放;
p2会存在至少两个实例,当内存池不够时容器会创建时新的并且加入到实例池,但是最多只有4个。是否比较难理解?我们拿孙悟空为例,虽然可以变出许多猴子,但是都是他的替身罢了。
p 3则总是新人,但愿谈恋爱的弟弟妹妹不要这样:-)
看看我们的测试片断:
[TestFixture]

public class LisfCycleTester
{
private SimpleContainer container;
[SetUp]

public void Init()
{
Hashtable ht=new Hashtable();
//ht.Add("qpg.email_sender",typeof(EmailSender));
container = new SimpleContainer(ht);
}
[TearDown]

public void Finish()
{
container.Dispose();
}


private void visitProduct(string key,int num)
{

Product p;
ArrayList ps=new ArrayList();

int i;

for( i=0;i<num;i++)
{
p=container[key] as Product;
Console.WriteLine("{0}--{1}",i+1,p.Price);
p.setPrice((i+1)*10);//看看是否实用了新对象
ps.Add(p);
}

for(i=0;i<ps.Count;i++)
{
container.Release(ps[i]);
}
ps.Clear();
}

private void visitPooledProduct(string key,int num)
{

Product p;
int i;

for( i=0;i<num;i++)
{
p=container[key] as Product;
Console.WriteLine("{0}--{1}",i+1,p.Price);
p.setPrice((i+1)*10);
container.Release(p);
}
}


private void runTest(string key)
{
long t1=System.Environment.TickCount;
visitProduct(key,4);
if(key!="p2") visitProduct(key,10000);
else visitPooledProduct(key,10000);
long t2=System.Environment.TickCount-t1;
Console.WriteLine("{0}ms",t2);
}

[Test]

public void tesSingleton()
{
runTest("p1");
}
[Test]

public void testPool()
{
runTest("p2");
}
[Test]

public void testMany()
{

runTest("p3");
}

让我们来看看执行的结果如何吧:
先运行tesSingleton
call Product()
call Product()
Product(P1,333,33)
1--333
2—10 //哈哈:第二次使用的还是那个对象,我们在前次给他的价格已经设置为10元了
3--20
4--30
1--40
2--10
3—20
。。。。。。
您可以看到系统先产生了2个Product,那是因为p2最少有两个,平台已经知道我们的期望,自动帮我们做了!
P1只被产生一次:Product(P1,333,33),这些初始值就是我们在配置文件里写的,不是吗?
在我的机器上运行10004次访问花费了1610ms
再看看testPool()
call Product()
1--0
2--0
call Product()
3--0
call Product()
4--0
1--40
2--10
3--20
4--30
5--40
6--50
7--60
8--70
9--80
。。。。。。
您可以看到虽然系统先产生了2个Product,但是在访问并且不释放情况下第三、四次访问时,系统调用了缺省构造函数来产生一个新的实例。以后使用访问并释放的方法,这四个实例满足了我们一万次的访问。在我的机器上,这个TestCase用了1687ms,也证明尽管有缓存,但是毕竟构造两次也花了些时间。所以没有Singleton快。
最后再看看每次都来个新的:
call Product()
call Product()
call Product()
1--0
call Product()
2--0
call Product()
3--0
call Product()
4--0
call Product()
1--0
call Product()
2--0
call Product()
3--0
call Product()
4--0
call Product()
。。。。。。
您可以看到确是每次都会产生新的,这样肯定最慢了,在我机器上用了4031ms。
测试程序里还演示了两个常用的功能,写日志和加密压缩。演示结果您可以在Debg\LOG\下发现一个log.txt,打开看看应该如下:
[DEBUG][2005-09-27 21:23:09,484]--hello world! SO SIMPLE!
是否太过简单?如果您了解log4net ,您可以配置成您想要的日志方式,比如写系统日志、谢数据库、远程对象、UDP广播等。
在看看加密压缩吧:
Zip:UEsDBBQAAAAIAEi0OzMnz+xKCgAAAAgAAAAHAAAARFRPLnhtbAsMcNcrSS0uAQBQSwECFAAUAAgACABItDszJ8/sSgoAAAAIAAAABwAAAAAAAAAAAAAAAAAAAAAARFRPLnhtbFBLBQYAAAAAAQABADUAAAAvAAAAAAA=
Encrypt:cvvPjAY7PxOBywAak7KOw6b5J157cRpVLm4pUWDJIc+i3ihSvn5OMahF1sFDrkckMxvLod78maAQppESMCKa0x9pJxvrZbN5i/rMMNSTfF6ffA57JhyhZSgNMrufC0daVX4g9eEJ8sQD5MTo+OPZAOjjZW+kVs4TvHa8gc5QA/4y9HAaEk7v/8kBV7ENGnHvSQii8sR9bTDjIF6k8YNZpXjISMH7iVfY
Decrypt:UEsDBBQAAAAIAEi0OzMnz+xKCgAAAAgAAAAHAAAARFRPLnhtbAsMcNcrSS0uAQBQSwECFAAUAAgACABItDszJ8/sSgoAAAAIAAAABwAAAAAAAAAAAAAAAAAAAAAARFRPLnhtbFBLBQYAAAAAAQABADUAAAAvAAAAAAA=
UnZip:QPG.test
这就是我们要的,是很简单,基本够用就好!
另外心细的读者会发现SimpleContainer.MessageQueue,这是干什么的呢?那是我们分布式处理的消息队列代理,且听下回分解......
(在没有正确配置时使用会报错喔!)