分享
 
 
 

VB.Net中文教程(11) Prototype样式

王朝vb·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

请注意 ......

著作权所有人:物泽计算机事业股份有限公司、

MISOO对象技术顾问团队、对象导向杂志作者、等。

u本文件摘自 对象导向杂志、精通对象观念与技术等书籍著作。

u本文件仅供您的参阅,请遵守著作权法,不得做其它商业用途。

主题: 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 Class Form1

Inherits System.WinForms.Form

Public Sub New()

MyBase.New()

Form1 = Me

'This call is required by the Win Form Designer.

InitializeComponent()

'TODO: Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.

Public Overrides Sub Dispose()

MyBase.Dispose()

components.Dispose()

End Sub

#Region " Windows Form Designer generated code "

......

#End Region

Protected Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs)

Dim list As New ShapeList()

Dim ps As Shape

ps = New Circle()

ps.SetXY(10, 10)

list.AddShape(ps)

ps = New Rectangle()

ps.SetXY(50, 50)

list.AddShape(ps)

ps = list.GetShape(0).Clone()

ps.SetXY(230, 70)

list.AddShape(ps)

list.Draw()

End Sub

End Class

此程序输出:

Draw a Circle at (10, 10)

Draw a Rectangle at (50, 50)

Draw a Circle at (230, 70)

ShapeList类别属于Client,在设计ShapeList类别时,只能用到Shape类别的信息而已;在Client(如上述的Form1类别)里,除了诞生对象时使用到Circle和Rectangle类别名称之外,也只能用到Shape类别的信息而已;这让我们未来能不断扩充更多子类别,如Square、Triangle等等。为了达到此高度扩充性,需要用到多形性(polymorphism)观念。所以Shape类别里建立了多形的基础:

Public Overridable Sub Draw()

End Sub

Public Overridable Function Clone() As Shape

End Function

Draw( )和Clone( )皆是虚拟(virtual)程序,以发挥多型(polymorphism)功能。lx及ly是图形的左上角坐标。SetXY( )可改变lx及ly值。ShapeList类别的Draw程序用来绘出串行中的各prototype对象图。

VB的父类别(superclass)有两种角色:

1) 提供一些程序给子类别继承

2) 作为各子类别的共同接口(Interface)

上述程序是两者合一的落实途径。如果您落实到分布式(Distributed)环境里,则宜将上述两项角色分离并各别落实之。此时必须使用VB的Interface机制了。例如上述程序相当于:

'ex02.bas

Imports System.ComponentModel

Imports System.Drawing

Imports System.WinForms

'----------------------------------------------------

Interface IShape

Sub Draw()

Function Clone() As IShape

Sub SetXY(ByVal x As Integer, ByVal y As Integer)

End Interface

Class Shape

Protected lx, ly As Integer

Protected Sub SetXY(ByVal x As Integer, ByVal y As Integer)

lx = x

ly = y

End Sub

End Class

Class Circle

Implements IShape

Inherits Shape

Public Sub Draw() Implements IShape.Draw

MessageBox.Show("Drawing a Circle at (" + str(lx) + ", " + str(ly) + ")")

End Sub

Public Function Clone() As IShape Implements IShape.Clone

Clone = New Circle()

End Function

Public Sub SetValue(ByVal x As Integer, ByVal y As Integer) Implements IShape.SetXY

MyBase.SetXY(x, y)

End Sub

End Class

Class Rectangle

Inherits Shape

Implements IShape

Public Sub Draw() Implements IShape.Draw

MessageBox.Show("Drawing a Rectangle at (" + str(lx) + ", " + str(ly) + ")")

End Sub

Public Function Clone() As IShape Implements IShape.Clone

Clone = New Rectangle()

End Function

Public Sub SetValue(ByVal x As Integer, ByVal y As Integer) Implements IShape.SetXY

MyBase.SetXY(x, y)

End Sub

End Class

'------------------------------------------------------------------------------------------

Class ShapeList

Private tlist(10) As IShape

Private counter As Integer

Public Sub New()

counter = 0

End Sub

Public Sub AddShape(ByVal sobj As IShape)

tlist(counter) = sobj

counter = counter + 1

End Sub

Public Function GetShape(ByVal i As Integer) As IShape

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 Class Form1

Inherits System.WinForms.Form

Public Sub New()

MyBase.New()

Form1 = Me

'This call is required by the Win Form Designer.

InitializeComponent()

'TODO: Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.

Public Overrides Sub Dispose()

MyBase.Dispose()

components.Dispose()

End Sub

#Region " Windows Form Designer generated code "

......

#End Region

Protected Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs)

Dim list As New ShapeList()

Dim pShape As IShape

pShape = New Circle()

pShape.SetXY(10, 10)

list.AddShape(pShape)

pShape = New Rectangle()

pShape.SetXY(50, 50)

list.AddShape(pShape)

pShape = list.GetShape(0).Clone()

pShape.SetXY(230, 70)

list.AddShape(pShape)

list.Draw()

End Sub

End Class

此程序输出:

Draw a Circle at (10, 10)

Draw a Rectangle at (50, 50)

Draw a Circle at (230, 70)

Shape类别专心担任幕后角色了,Client及ShapeList类别的设计者只看到IShape接口而已,这充分发挥了VB接口的优点。

4. Prototype样式之应用

----- 组件之设计与组装

软件工业逐渐往零组件或称组件(component) 方向发展﹐未来计算机软件人员将分为两大群﹕对象设计者(object designer) 与对象装配者(object assembler)。就拿VB 程序员来说﹐对象设计者负责设计类别﹐以便诞生出各式各样之对象﹔对象装配者能使用现有对象或将之组装成更大之对象或系统。

依据上述加菲猫和西施的例子中﹐人们常很自然地拿自己熟悉的例子来描述他所想要的对象﹔亦即经由举例来说明他心中的对象﹐是较合乎人们生活习惯的。反而较少以类别来描述他心中之对象。因之﹐对象设计者定义好各类别之后也应各诞生一个对象﹐当做例子(prototype) ﹐最好显示在Windows 画面上。对象装配者不需要具有「类别」观念﹐只需用鼠标点取画面上的prototype 对象﹐就能获得一个类似的新对象了。如此﹐就可构成美好的分工情形。然而﹐在VB及Java等语言中﹐对象皆是由「类别」来产生的。这会造成冲突问题﹕

u 设计者不能随时诞生对象供装配者使用﹐因而希望装配者随时藉由类别诞生对象。

u 装配者最好不必具有类别观念﹐因而不愿意藉由类别来诞生对象。

如何化解这个问题呢﹖答案是﹕使用prototype 样式。

对象设计者之工作包括:

1. 设计(定义)一个Form类别叫Form1。

2. 设计一个应用架构(application framework)做为「设计者」与「装配者」分工的基础。

3. 基于架构,衍生出子类别,如Circle及Rect。

4. 诞生对象,存入串行ShapList中,如图3所示。

图3、组装的基础环境

对象装配者之工作是:

点取(或使讯息)给串行中的prototype对象,由其呼叫Clone( )来诞生新对象。

例如,让「装配者」自屏幕画面上选取对象。Circle和Rectangle各定义Draw( )及Clone( )达到多型效果,让「装配者」使用起来更加方便。Clone( )必传回一个新对象。Form1.Click()里的指令-----

pShape = list.GetShape(0).Clone()

pShape.SetXY(230, 70)

list.AddShape(pShape)

首先,取出串行中的第0个prototype对象,此对象诞生另一个对象,由pShape代表之。在将此新对象存入串行中,如下图所示:

图4、组装者依据prototype指示计算机诞生对象

最末将各prototype对象数示于画面上。

上述例子中,把ShapeList也归为对象设计者的掌管工作之一。在实际上,ShapeList常隶属于「装配工具」(assembly tools)内的一部份。而装配工具的设计者,可能既非对象设计者,也非对象装配者,而是用来协助「装配者」使其工作效率更佳。

由于Clone函数及Draw( )程序的多型性,在加上Clone( )能产生新对象,使得装配工具设计者,不必顾虑到对象类别之剧增,也不必用到期类别名称,大大减少工具程序之复杂度,这也是prototype模式的另一个重要用途。■

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有