定 义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象,Prototype模式同工厂模式,同样对客户隐藏了对象的创建工作,但是,与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的,达到了“隔离类对象的使用者和具体类型(易变类)之间的耦合关系”的目的。
优 点:
1、性能优良,特别是在循环内产生大量对象时,原型模式可以更好的体现优点
2、逃避构造函数的约束,拷贝不会执行构造函数
3、它对客户隐藏了具体的产品类,因此减少了客户知道的名字的数目。
4、Prototype模式允许客户只通过注册原型实例就可以将一个具体产品类并入到系统中,客户可以在运行时刻建立和删除原型。
5、减少了子类构造,Prototype模式是克隆一个原型而不是请求工厂方法创建一个,所以它不需要一个与具体产品类平行的Creater类层次。
6、Portotype模式具有给一个应用软件动态加载新功能的能力。由于Prototype的独立性较高,可以很容易动态加载新功能而不影响老系统。
7、产品类不需要非得有任何事先确定的等级结构,因为Prototype模式适用于任何的等级结构
使用场景:
1、资源优化场景
2、性能和安全要求的场景
3、一个对象多个修改者的场景
4、当一个系统应该独立于它的产品创建,构成和表示时;
5、当要实例化的类是在运行时刻指定时,例如,通过动态装载;
6、为了避免创建一个与产品类层次平行的工厂类层次时;
7、当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
概 述:在软件系统中,有时候面临的产品类是动态变化的,而且这个产品类具有一定的等级结构。这时如果用工厂模式,则与产品类等级结构平行的工厂方法类也要随着这种变化而变化,显然不大合适。那么如何封装这种动态的变化?从而使依赖于这些易变对象的客户程序不随着产品类变化?
1.为什么需要Prototype模式?
引入原型模式的本质在于利用已有的一个原型对象,快速的生成和原型对象一样的实例。你有一个A的实例a:A a = new A();现在你想生成和car1一样的一个实例b,按照原型模式,应该是这样:A b = a.Clone();而不是重新再new一个A对象。通过上面这句话就可以得到一个和a一样的实例,确切的说,应该是它们的数据成员是一样的。Prototype模式同样是返回了一个A对象而没有使用new操作
2.引入Prototype模式带来了什么好处?
可以看到,引入Prototype模式后我们不再需要一个与具体产品等级结构平行的工厂方法类,减少了类的构造,同时客户程序可以在运行时刻建立和删除原型。
3.Prototype模式满足了哪些面向对象的设计原则?
依赖倒置原则:上面的例子,原型管理器(ColorManager)仅仅依赖于抽象部分(ColorPrototype),而具体实现细节(ConcteteColorPrototype)则依赖与抽象部分(ColorPrototype),所以Prototype很好的满足了依赖倒置原则。
理 解:先来看看原型模式的类图结构,ProtyType必须要实现Clone方法
下面来看看在系统中实现一个颜色索引器的例子,子类复制
再来看一个群发邮件的设计:
Public Class AdvTemplate
Private m_advSubject As String
Private m_advContext As String
Public Property advSubject() As String
Get
Return m_advSubject
End Get
Set(ByVal Value as String)
m_advSubject = Value
End Set
End Property
Public Property advContext() As String
Get
Return m_advContext
End Get
Set(ByVal Value as String)
m_advContext = Value
End Set
End Property
End Class ' AdvTemplate
Public Class Mail
Implements ICloneable
Private m_receiver As String
Private m_subject As String
Private m_appellation As String
Private m_context As String
Private m_tail As String
Private m_tag As Integer = 0
Public Property Tag() As Integer
Get
Return m_tag
End Get
Set(ByVal value As Integer)
m_tag = value
End Set
End Property
'''
''' <param name="_advTemplate"></param>
Public Sub New(ByVal _advTemplate As AdvTemplate)
m_subject = _advTemplate.advSubject
m_context = _advTemplate.advContext
End Sub
Public Property receiver() As String
Get
Return m_receiver
End Get
Set(ByVal Value As String)
m_receiver = Value
End Set
End Property
Public Property subject() As String
Get
Return m_subject
End Get
Set(ByVal Value As String)
m_subject = Value
End Set
End Property
Public Property appellation() As String
Get
Return m_appellation
End Get
Set(ByVal Value As String)
m_appellation = Value
End Set
End Property
Public Property context() As String
Get
Return m_context
End Get
Set(ByVal Value As String)
m_context = Value
End Set
End Property
Public Property tail() As String
Get
Return m_tail
End Get
Set(ByVal Value As String)
m_tail = Value
End Set
End Property
Public Function Clone() As Object Implements System.ICloneable.Clone
Dim _mail As Mail = DirectCast(MemberwiseClone(), Mail) '浅表副本复制
Return _mail
Return Me
'Dim oNewCar As Mail = DirectCast(oOriginalCar.Clone, Mail)
End Function
End Class ' Mail
Module Client
Sub Main()
Dim MAX_Count As Integer = 6
Dim _template As AdvTemplate = New AdvTemplate
_template.advSubject = "发工资通知"
_template.advContext = "请大家提前做好换银行卡的准备"
Dim _mail As Mail = New Mail(_template)
_mail.tail = "新动传媒版权所有"
_mail.Tag = _mail.Tag + 1
For i As Integer = 0 To MAX_Count - 1
Dim cloneMail As Mail = _mail.Clone()
cloneMail.Tag = cloneMail.Tag + 1
cloneMail.appellation = i & "先生/女式:"
cloneMail.receiver = i & "@magnmedia.com"
SendMail(cloneMail)
Next
Console.Read()
End Sub
Private Sub SendMail(ByVal _mail As Mail)
Console.WriteLine(_mail.Tag & "标题:" & _mail.tail & " 收件人:" & _mail.receiver & " 邮件内容:" & _mail.context)
End Sub
End Module