学习设计模式:原型,让我们更安全

本文介绍了如何利用原型模式解决C#中对象引用可能导致的未知状态问题。通过实现原型模式,每次请求对象时返回的是原对象的拷贝,避免了客户端对对象的修改影响到原始对象。在PatternTester类中实现IClonable接口,提供了一个浅拷贝方法,确保了对象的安全使用。原型模式的应用简化了代码,增强了程序的健壮性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



上一篇博文提到,现在搭建起来的测试平台大多数情况下可以工作得不错,但是还有一个重要缺陷,每次运行的PatternTester子类对象是从testerList中获取的,而在C#中,对象是属于引用类型,赋值过程只是增加了这个对象的引用,任何一个引用上发生的改变都会反映到其他引用上,因此假设我们在客户端(Main函数)中改变了运行中的tester对象,例如令其等于null,那么testerList该对象的引用也将指向null,如果客户端再一次到testerList中取该对象,那么将会获得一个null对象,于是程序接下来的运行就进入了一个完全未知的状态。为了防止这种情况发生,可以使用原型模式轻松实现。

原型模式是指通过已经存在的对象拷贝自身(有深浅拷贝之分,并且使用不同的拷贝方式对程序影响比较大)来产生一个新的对象,新对象的请求者不需要知道具体的类型。具体到测试平台中就是每次请求PatternTester子类对象时,不是直接返回testerList中对象的引用,而是让该对象拷贝自身,然后返回这份拷贝,即将:

public PatternTester CreatePatternTester(string patternType)

{

PatternTester tester = null;

try

{

Tester =testerList[patternName];

}

catch

{

 Tester = new NotInBookPatternTester();

}

retutn tester;

}

变为:

public PatternTester CreatePatternTester(string patternType)

{

PatternTester tester = null;

try

{

//Clone()函数拷贝自身

//Tester并不知道该对象的实际类型

Tester =testerList[patternName].Clone();

}

catch

{

   Tester = new NotInBookPatternTester();

}

retutn tester;

}

可以看到,变化非常小,不必为每一个PatternTester子类都实现该方法,只需在父类PatternTester中增加此方法并将其设为虚函数,编写一份缺省的实现,子类可以根据需要决定是否续写此方法。而在C#中,只需让父类PatternTester类实现IClonable接口,如下:

 

publicabstractclass IPatternTester: ICloneable,IDisposable

   {

       private boolIsDisposed = false;

       

       //实现ICloneable接口,必须实现此方法,这也是我们需要的

       public Object Clone()

       {

           //.MemberwiseClone().NET提供的一个浅拷贝方法,由于

           //PatternTester类并没有引用类型的数据成员,浅拷贝足矣

           return (Object)this.MemberwiseClone();

       }

       public voidDispose()

       {

           IsDisposed = true;

       }

       protectedvirtualvoid RequireInput()

       {

        

       }

       protected virtualvoid RunTest()

       {

 

       }

       protected virtualvoid ShowOutput()

       {

    

       }

       public voidRun()

       {

           if (IsDisposed ==true)

               thrownewNullReferenceException();

           RequireInput();

           RunTest();

           ShowOutput();

       }

   }

至此,在原型模式的帮助下,PatternTester子类实例对象在客户端的更改不再会影响到testerList中的对象,用户每次向PatternTesterFactory类请求tester实例时就可以保证得到一个符合预期的有效引用。好了,原型模式就是这么简单,但却让我们更加安全地自由地使用对象!当然原型模式的好处并不止这一个,实际上前面提到的另外三个模式也还有许多其他的好处,这会在下一篇文章里陈述。

下一篇文章会简单描述一个新的模式——工厂方法,之所以说简单地描述一下,是因为工厂方法和简单工厂非常相似,而由于C#语言的特殊性,使得这种相似性又增加不少。描述完工厂方法后,将对这五个模式进行总结并谈谈自己的感受。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值