类工厂模式

面向对象设计的一个目标就是将各种功能封装到不同的对象.这种思想很好,鼓励使用封装和委托.

有些应用程序或框架无法预料必须被创建的对象的类型.通常先接收一些信息指示如何执行.

这种情形在RO服务端接收到客户端请求是经常要面对:服务端需要知道请求需要什么对象,需要创建一个实例,最终调用完成, 又需要决定如何处理这个创建的实例.

我们使用类工厂模式来解决这中变异.

注意:本文适合RemObjects SDK Delphi.NET版本. 对只适用于一种版本的将标注.

数据库连接池

很多可用的Delphi架构都是以数据为中心的.这可以适应简单应用,但当需要池和线程安全存取对象时很快就崩溃了.

RemObjects SDK提供数据库连接池的支持:允许你线程安全的缓冲服务对象实例. 同时你也可以为你的对象选择其他的实例化模式.

如何控制使用的实例化模式

For Delphi xxxx_Impl.pas单元的initialization节中设置适当的类工厂. 下面是MegaDemo 范例的NewService_Impl.pas代码:

initialization

TROClassFactory.Create('NewService', Create_NewService,

                         TNewService_Invoker);

TROClassFactory使用单独调用对象模式激活(per-call). 这意味着每个对NewService的调用都会生成一个新的服务实例,调用支持完毕马上释放.如果你希望对NewService服务生成大小为4的缓冲池,使用如下代码:

initialization

TROPooledClassFactory.Create('NewService', Create_NewService,

                               TNewService_Invoker, 4);

For .NET, RemObjects SDK 在定义服务是使用指定属性, .

[RemObjects.SDK.Server.ClassFactories.StandardClassFactory()]

[RemObjects.SDK.Server.Service(Name="MegaDemoService",

                          InvokerClass=typeof(MegaDemoService_Invoker))]

public class MegaDemoService : RemObjects.SDK.Server.Service, IMegaDemoService {

Delphi的情形,标准的类工厂为每个调用创建一个新实例,调用后马上释放..NET中使用缓冲池,可以修改制订属性使用PooledClassFactory属性替换.例如创建缓冲大小为4的实例:

[RemObjects.SDK.Server.ClassFactories.PooledClassFactory(4)]

可用的类工厂

类工厂如下表:

  • Delphi: TROClassFactoryuROServer.pas单元,其他类工厂在uROClassFactories.pas单元.
  • .NET: 全部定义在RemObjects.SDK.Server.ClassFactories命名空间.

 

 

 

SDK可用如下实例化模式和类工厂:

模式

类工厂 (Delphi)

类工厂(.NET)

Per-call (默认每个调用创建一个实例)

TROClassFactory

StandardClassFactory

Per-client (每个客户端一个实例)

TROPerClientClassFactory

PerClientClassFactory

Singleton(单例模式所以客户端所有调用共用一个实例) – 1

TROSingletonClassFactory

SingletonClassFactory

Synchronized Singleton(同步缓冲池模式)

TROSynchronizedSingletonClassFactory

2

Pooled(缓冲池模式)

TROPooledClassFactory

PooledClassFactory

:
1)
Singleton模式是非线程安全的(其他模式都是线程安全的)..
2)
.NETSingleton模式支持同步和非同步通讯. 对与同步的你需要设置SingletonBehaviorWait状态.

 

 

TROClassFactory/StandardClassFactory

这是默认的类工厂.每当接到请求时,都会在服务端创建一个新实例,执行请求后释放.由于对与每个请求都是在单独进程的单独实例中执行,所以对类内的成员调用都是线程安全的.例如如果在服务对象类中创建一个组件,你可以放心使用它,而不用担心其他线程的锁定.

这种实例化模式是最据可扩展行的,这种思想源于Web情形.

For Delphi, 构造函数声明如下:

constructor Create(const anInterfaceName: string;

                   aCreatorFunc: TRORemotableCreatorFunc;

                   anInvokerClass: TROInvokerClass);

For .NET, 通过订制属性指定所以没有构造函数参数.

TROPerClientClassFactory/PerClientClassFactory

这种类工厂保证客户端连续的调用同一个服务对象.对象在客户端第一次连接后创建,在对象闲置时间超过Timeout-seconds后释放.

这种实例化模式可扩展性差并消耗资源. 我们不推荐使用这种模式, 但在开发DataSnap应用时很有用.

For Delphi,你也可以通过编程控制对象的释放,对象要实现IRODestructorController接口并让CanBeDestroyed方法返回True.在每次调用后类工厂都会检查这个函数并做相应的操作.

TROPerClientClassFactory的构造函数声明如下:

constructor Create(const anInterfaceName: string;

                   aCreatorFunc: TRORemotableCreatorFunc;

                   anInvokerClass: TROInvokerClass;

                   aTimeoutSeconds: cardinal);

For .NET, PerClientClassFactory 的制订属性没有参数,但有两个域:

  • Int Timeout:超时的秒数,默认为10
  • Bool AllowConcurrentAccess: 当设置为True,多个具有相同SessionID的可同时连接到服务,默认为False.

TROSingletonClassFactory/SingletonClassFactory

这个类工厂只创建一个服务对象实例,使用时需要自己控制线程安全. 因为不支持线程安全所以使用内部成员时需要人为的增加线程同步控制.

这个实例模式效率很好,但是控制很复杂. 一个实例可能会同时处理多个请求,所以必须重视线程安全.

For Delphi, TROSingletonClassFactory 构造函数声明如下:

constructor Create(const anInterfaceName: string;

                   aCreatorFunc: TRORemotableCreatorFunc;

                   anInvokerClass: TROInvokerClass);

For .NET, 有两个重载的构造函数:

public SingletonClassFactoryAttribute()

public SingletonClassFactoryAttribute(SingletonBehavior aSingletonBehavior)

SingletonBehavior参数可以设置为Multiple, Wait Fail. Multiple (默认)允许多个客户端请求同时在一个服务实例上执行. Wait 选项要等待服务实例空闲时才能处理请求, 保证同时只有一个实例运行. Fail 选项当服务实例正在运行时引发调用错误.

TROSynchronizedSingletonClassFactory

这个类工厂只创建一个对象实例,所有请求线程顺序的使用.框架自动为你实现了线程安全和对象内成员访问的线程同步.

这个实例化模式不是很有效率,但是当需要顺序访问外部资源(如访问文件或主机连接)是很有用.

TROSynchronizedSingletonClassFactory 构造函数声明如下:

constructor Create(const anInterfaceName: string;

                   aCreatorFunc: TRORemotableCreatorFunc;

                   anInvokerClass: TROInvokerClass);

TROPooledClassFactory/PooledClassFactory

这个类工厂持有指定数量的对象实例,并提供了线程安全的访问接口.

For Delphi, TROPooledClassFactory构造函数声明如下:

constructor Create(const anInterfaceName: string;

                   aCreatorFunc: TRORemotableCreatorFunc;

                    anInvokerClass: TROInvokerClass;

                   aPoolSize: Integer;

                   aPoolBehavior:TROPoolBehavior=pbCreateAdditional;

                   aPreInitializePool:Boolean=false);

设置aPreInitializePool参数为TRUE时类工厂创建后将填充线程池.

当请求数量达到最大时, PoolBehavior 参数觉得如何处理.aPoolBehavior可以设置为pbFail, pbWait, pbCreateAdditional. 服务终止后对象被释放.

For .NET, 有四个重载的构造函数:

public PooledClassFactoryAttribute()

public PooledClassFactoryAttribute(int aPoolSize)

public PooledClassFactoryAttribute(int aPoolSize, PoolBehavior aPoolBehavior)

public PooledClassFactoryAttribute(int aPoolSize, PoolBehavior aPoolBehavior, bool aPreInitializePool)

PoolSize参数指定缓冲池的大小.

aPoolBehavior 参数可以设置为:

  • CreateAdditional: 池中没有可用实例时创建更多的实例但用完释放不放在缓冲池中
  • Wait: 池中没有可用实例时等待
  • Fail: 池中没有可用实例时使请求失败.

aPreIntializePool参数指定是否在启动时预先生成aPoolSize个服务对象实例.

默认缓冲池大小为5, PoolBehavior Fail, PreInitializePool false.

 

 

 

 

RO 可以使用的线程模式有:
1.TROClassFactory
:默认的方式,每个连接都建立一个接口对象,用完即销毁。CPU占用率极高( ISAPI),比较稳定。
2.TROSingletonClassFactory
:单实例模式,所有连接共享一个实例,可能存在线程冲突。
3.TROSynchronizedSingletonClassFactory
:同步单实例模式,所有连接共享一个实例但必须一个一个的按顺序访问,是线程安全的模式,但效率低,CPU 占用率也低。
4.TROPerClientClassFactory
:每个客户端一个连接(以ClinetID为准),效率高。也可以称为一个Session一个实例,Session在一定时间内不活动就会销毁实例。
5.TROPooledClassFactory
:连接池模式,效率很好,但CPU占用率也高些。连接池的大小可以根据情况调节,而且对超过连接池大小的新连接,可以在返回错误、等待或新建实例中选择操作。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值