日期:2009-02-01  浏览次数:20419 次

主题: Prototype样式
副题: 多形性、接口(Interface)


????????? 内容 ?????????

v 1. 样式
v 2. 对象之原型(object prototype)
v 3. 以VB落实Prototype样式
v 4. Prototype样式之应用----- 组件之设计与组装


1. 样式
Erich Gamma 等人的名著──"Design Patterns: Elements of Reusable Object-Oriented Software" 含有23个重要的设计样式(design pattern)。顾名思义﹐「样式」就是大家可「有样学样﹐依样画葫芦」﹐并一而再、再而三地在不同场合﹐重复使用(reuse) 它来解决常见之问题。
样式必须常常使用﹐且愈纯熟愈好﹐才能随外界环境(context) 而加以变化﹐才能确实解决问题(problem) 。像孙子兵法、太极拳法皆含有许多样式(或称为招式)﹐必须心领神会﹐并实际练习之﹐才能达到炉火纯青之地步。其主要原因是﹕单一样式(招式)常只解决个小问题﹐而大问题可能需要多种样式混合使用才行。如何将小样式组合成为大样式来解决大问题呢﹖这常需一套完整的法则(rule)﹐通称为「样式语言」(pattern language)。本文引用Gamma书中的Prototype样式﹐说明如何以VB的接口来实作之,也让您更能善用多形性观念。以下就请您仔细看如何使用Prototype 样式了。


图1、Prototype样式的UML图


2. 对象之原型 (object prototype)
人们日常生活中﹐常见下述说法﹕

「我要养一只像加菲猫一样的猫」
「我将来要娶个美如西施的妻子」
......

其中﹐加菲猫和西施皆是prototype (或译为范例)。当您说上述两句话时﹐听者立即能经由prototype 对象(即加菲猫或西施)来了解您心中所欲描述之新对象。在软件方面﹐使用者可藉prototype 来告诉计算机﹕

「我要的对象就像这个prototype 对象」

于是﹐计算机依该prototype 对象来造出一模一样的新对象给使用者。
回想﹐我们所熟悉的VB、C#、Java或C++语言中﹐皆是借着「类别」来描述对象之特性﹐然后计算机则依类别之描述来造出新对象。这种就通称为class-based programming ﹔而前者称为prototype-based programming 。
随着﹐软件零组件(sofrware IC) 观念的流行﹐prototype-based programming 观念也愈来愈重要了。既使像VB语言﹐也能支持prototype-based programming 。


3. 以VB落实Prototype样式
上图1是Gamma书中所列出的prototype样式。下图2则是个实际的例子。


图2、绘图对象的Prototype

对象设计者从Shape衍生出Circle及Rectangle两类别,并各诞生1个prototype对象,且存入ShapeList串行或数组之中。设计者必须为各类别定义Clone( )函式来诞生新对象,并构成多形性。于是对象装配者只需呼叫Clone( )函数就能获得新对象,而不必具有类别观念。未来,设计者可从Shape类别衍生出许许多多子类别,并把对象放入ShapeList中,供装配者使用。
兹看看如何以VB来落实上图2的UML模式:

'ex01.bas
Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
'-------------------------------------------------------------------------
Class Shape
Protected lx, ly As Integer
Public Sub SetXY(ByVal x As Integer, ByVal y As Integer)
lx = x
ly = y
End Sub
Public Overridable Sub Draw()
End Sub
Public Overridable Function Clone() As Shape
End Function
End Class

Class Circle
Inherits Shape

Public Overrides Sub Draw()
MessageBox.Show("Drawing a Circle at (" + str(lx) + ", " + str(ly) + ")")
End Sub
Public Overrides Function Clone() As Shape
Clone = New Circle()
End Function
End Class

Class Rectangle
Inherits Shape

Public Overrides Sub Draw()
MessageBox.Show("Drawing a Rectangle at (" + str(lx) + ", " + str(ly) + ")")
End Sub
Public Overrides Function Clone() As Shape
Clone = New Rectangle()
End Function
End Class
'-------------------------------------------------------------------------------------
Class ShapeList
Private tlist(10) As Shape
Private counter As Integer

Public Sub New()
counter = 0
End Sub
Public Sub AddShape(ByVal sobj As Shape)
tlist(counter) = sobj
counter = counter + 1
End Sub
Public Function GetShape(ByVal i As Integer) As Shape
GetShape = tlist(i)
End Function
Public Sub Draw()
Dim i As Integer
For i = 0 To counter - 1
tlist(i).Draw()
Next
End Sub
End Class
'-------------------------------------------------------------------------------------
Public Cla