设计模式.docx
- 文档编号:10343182
- 上传时间:2023-02-10
- 格式:DOCX
- 页数:31
- 大小:293.41KB
设计模式.docx
《设计模式.docx》由会员分享,可在线阅读,更多相关《设计模式.docx(31页珍藏版)》请在冰豆网上搜索。
设计模式
1,
FromGossip@caterpillar
DesignPattern:
SimpleFactory模式
SimpleFactory模式(又称StaticFactory模式),一个SimpleFactory生产成品,而对客户端隐藏产品产生的细节。
实作时定义一个产品介面(interface),并透过特定静态方法来建立成品。
假设有一个音乐盒工厂,购买音乐盒的客人不用知道音乐盒是如何制作的,他只要知道如何播放音乐盒就可以了,以UML类别图来表示以上的概念:
如上图所示的,MusicBoxDemo代表了客户的角色,它只依赖于IMusicBox介面,而不关心特定的实作,实际如何产生IMusicBox的实例由MusicBoxFactory完成,以一个简单的程式来实现上面这个UML类别图:
∙IMusicBox.java
publicinterfaceIMusicBox{
publicvoidplay();
}
∙PianoBox.java
publicclassPianoBoximplementsIMusicBox{
publicvoidplay(){
System.out.println("拨放钢琴音乐:
)");
}
}
∙ViolinBox.java
publicclassViolinBoximplementsIMusicBox{
publicvoidplay(){
System.out.println("拨放小提琴音乐^_^");
}
}
∙MusicBoxFactory.java
publicclassMusicBoxFactory{
publicstaticIMusicBoxcreateMusicBox(Stringname)
throwsInstantiationException,
IllegalAccessException,
ClassNotFoundException{
//这边使用的是Java的Reflection机制来产生实例
//不过客户端不用管啦
//以后就算改变了这边的程式,客户端程式是不用更改的
return(IMusicBox)Class.forName(name).newInstance();
}
}
∙MusicBoxDemo.java
publicclassMusicBoxDemo{
publicstaticvoidmain(String[]args)throwsException{
playMusicBox(MusicBoxFactory.createMusicBox("PianoBox"));
playMusicBox(MusicBoxFactory.createMusicBox("ViolinBox"));
}
publicstaticvoidplayMusicBox(IMusicBoxmusicBox){
musicBox.play();
}
}
由于客户端只依赖于IMusicBox介面,所以即使您日后改变了createMusicBox()中的实作方式,对客户端是一点影响也没有的。
来看看SimpleFactory的类别结构:
客户只要面对Factory,客户依赖于产品介面,产品的具体实作是可以与客户隔开的,它们也是可以抽换的。
2,
FromGossip@caterpillar
DesignPattern:
AbstractFactory模式
假设您要制作一个对话方块(Dialog)元件,您希望的是这个对话方块可以有不同的视感(Look-and-feel),最基本的想法是,藉由Setter将不同视感的元件设定给这个对话方块,例如:
∙CustomDialog.java
publicclassCustomDialog{
privateIButtonbutton;
privateITextFieldtextField;
publicvoidsetButton(IButtonbutton){
this.button=button;
}
publicvoidsetTextField(ITextFieldtextField){
this.textField=textField;
}
publicvoidlayoutAllComponents(){
//....
}
publicvoidshowDialog(){
this.paintDialog();
button.paintButton();
textField.paintTextField();
}
publicvoidpaintDialog(){
System.out.println("customdialogpaints....");
}
}
很简单,这是最基本的介面依赖,Setter依赖于IButton与ITextField两个介面,而不是其实作类别,不过这边还有个进一步的要求,使用上面的方式还必须亲自呼叫Setter、layout等方法,您希望视感的更换可以更简单些,例如只要透一个元件的替换就可以完成对话方块上所有元件的视感更换。
您可以使用AbstractFactory模式,将所有对话方块所需要的产生的元件加以封装,对话方块依赖于AbstractFactory,实际上具体的Factory实现则分别产生对话方块所需要的视感元件,下面的UML类别图展现这种概念。
现在如果要更换所有的视感元件,就只要抽象掉具体的Factory就可以了,例如:
CustomDialogwindowsDialog=
newCustomDialog(newWindowsWidgetFactory());
windowsDialog.showDialog();
CustomDialogmacDialog=
newCustomDialog(newMacWidgetFactory());
macDialog.showDialog();
来将上面的UML图具体实现出来。
∙CustomDialog.java
publicclassCustomDialog{
privateIButtonbutton;
privateITextFieldtextField;
publicCustomDialog(IWidgetFactorywidgetFactory){
setWidgetFactory(widgetFactory);
}
//由于客户端只依赖于抽象的工厂,工厂如何实作并无关客户端的事
//要抽换工厂并不需要改动客户端的程式
publicvoidsetWidgetFactory(IWidgetFactorywidgetFactory){
setButton(widgetFactory.getButton());
setTextField(widgetFactory.getTextField());
}
publicvoidlayoutAllComponents(){
//layoutallcomponents
}
//这边也是依赖抽象,实际改变了元件实例
//客户端代码也不用更改
publicvoidsetButton(IButtonbutton){
this.button=button;
}
publicvoidsetTextField(ITextFieldtextField){
this.textField=textField;
}
publicvoidshowDialog(){
this.paintDialog();
button.paintButton();
textField.paintTextField();
}
publicvoidpaintDialog(){
System.out.println("customdialogpaints....");
}
}
∙IButton.java
publicinterfaceIButton{
publicvoidpaintButton();
}
∙ITextField.java
publicinterfaceITextField{
publicvoidpaintTextField();
}
∙IWidgetFactory.java
publicinterfaceIWidgetFactory{
publicIButtongetButton();
publicITextFieldgetTextField();
}
∙MacButton.java
publicclassMacButtonimplementsIButton{
publicvoidpaintButton(){
System.out.println("Macbuttonpaints....");
}
}
∙WindowsButton.java
publicclassWindowsButtonimplementsIButton{
publicvoidpaintButton(){
System.out.println("Windowsbuttonpaints....");
}
}
∙MacTextField.java
publicclassMacTextFieldimplementsITextField{
publicvoidpaintTextField(){
System.out.println("MactextFieldpaints....");
}
}
∙WindowsTextField.java
publicclassWindowsTextFieldimplementsITextField{
publicvoidpaintTextField(){
System.out.println("WindowstextFieldpaints....");
}
}
∙MacWidgetFactory.java
publicclassMacWidgetFactoryimplementsIWidgetFactory{
publicIButtongetButton(){
returnnewMacButton();
}
publicITextFieldgetTextField(){
returnnewMacTextField();
}
}
∙WindowsWidgetFactory.java
publicclassWindowsWidgetFactory
implementsIWidgetFactory{
publicIButtongetButton(){
returnnewWindowsButton();
}
publicITextFieldgetTextField(){
returnnewWindowsTextField();
}
}
下图是AbstractFactory模式的UML结构图:
简单的说,在AbstractFactory模式中将具体的Product封装在具体Factory实现中,而客户仍只要面对Factory与Product的抽象介面,避免依赖于具体的Factory与Product,由于Factory封装了所必须的Product,所以要更换掉所有的元件,只要简单的抽换掉Factory就可以了,不用修改客户端的程式。
3,
FromGossip@caterpillar
DesignPattern:
Builder模式
您想要建立一个迷宫产生程式,迷宫使用二维阵列来定义,0表示道路,1表示墙,2表示宝物,根据所定义的二维迷宫阵列,您想要程式自动产生各种不同材质的迷宫,例如砖墙迷宫,钻石迷宫等等。
您可以在程式中定义两个角色,一个是指导迷宫建立的Director角色,一个是按照指导者指示建立迷宫的Builder角色,Director根据定义的迷宫阵列来指导Builder,只要更换Builder,就可以完成不同材质的迷宫。
可以使用下面的UML类别图来表示上述的概念:
实际上的程式设计如下:
∙MazeDirector.java
publicclassMazeDirector{
privateint[][]maze;
privateIMazeBuildermazeBuilder;
publicvoidsetMaze(int[][]maze){
this.maze=maze;
}
publicvoidsetMazeBuilder(IMazeBuildermazeBuilder){
this.mazeBuilder=mazeBuilder;
}
publicvoidbuildMaze(){
for(inti=0;i for(intj=0;j //由于mazeBuilder是IMazeBuilder型态 //所以无论Builder实例为何,这边的程式都无需变动 switch(maze[i][j]){ case0: mazeBuilder.createRoadBlock(); break; case1: mazeBuilder.createWallBlock(); break; case2: mazeBuilder.createTreasureBlock(); break; default: System.out.println("undefined"); } } mazeBuilder.nextRow(); } } } ∙IMazeBuilder.java publicinterfaceIMazeBuilder{ publicvoidcreateRoadBlock(); publicvoidcreateWallBlock(); publicvoidcreateTreasureBlock(); publicvoidnextRow(); } ∙SoliderMazeBuilder.java publicclassSolidMazeBuilderimplementsIMazeBuilder{ publicvoidcreateWallBlock(){ System.out.print("█"); } publicvoidcreateRoadBlock(){ System.out.print(" "); } publicvoidcreateTreasureBlock(){ System.out.print("$"); } publicvoidnextRow(){ System.out.println(); } } ∙DiamondMazeBuilder.java publicclassDiamondMazeBuilderimplementsIMazeBuilder{ publicvoidcreateWallBlock(){ System.out.print("◇"); } publicvoidcreateRoadBlock(){ System.out.print(" "); } publicvoidcreateTreasureBlock(){ System.out.print("*"); } publicvoidnextRow(){ System.out.println(); } } 使用下面的程式来测试一下,它将产生两个迷宫图形: publicclassMain{ publicstaticvoidmain(String[]args){ int[][]maze={{1,1,1,1,1,1,1}, {1,0,0,0,0,2,1}, {1,0,1,0,1,0,1}, {1,0,2,1,0,1,1}, {1,1,0,1,0,1,1}, {1,0,0,2,0,0,1}, {1,1,1,1,1,1,1}}; MazeDirectormazeDirector=newMazeDirector(); mazeDirector.setMaze(maze); System.out.println("BuildSolidMaze...."); mazeDirector.setMazeBuilder(newSolidMazeBuilder()); mazeDirector.buildMaze(); System.out.println("BuildDiamondMaze...."); mazeDirector.setMazeBuilder( newDiamondMazeBuilder()); mazeDirector.buildMaze(); } } 在迷宫例子中并没有产生或返回产品物件,这视您的需求而定,迷宫例子只是将结果输出至主控台,您也可以设计一个产品物件,或是将结果直接输出为文件。 在Gof中有给出了一个不错的例子,以设计文件剖析器为例,该剖析器可以将文件转换为其它的格式,以DOC文件剖析器为例好了,假设希望析剖器可以将DOC文件转换为RTF或是PDF文件,可以如下设计结构: 简单来说,建筑者模式适用的场合,在于使得您可以依赖抽象的建筑蓝图,而实际建造时可以使用不同的实例,这是其之所以命为Builder的原因。 4, FromGossip@caterpillar DesignPattern: FactoryMethod模式 考虑一个状况,您所经营的工厂正在生产一个新的电视机产品,现在有一个问题发生了,您的电视机产品所有的组件都可以自行生产,像是操作面版、电源、摇控装置等等等,但荧幕却必须依赖另一个厂商或子厂商供应,这时您怎么办? 您不能将生产进度停下了,相反的您必须确定一些事情,您知道有关于荧幕控制的所有介面,您可以将这些对介面的操作沟通先实现,等到荧幕到了,直接将荧幕与您的半成品组合起来,一个完整的成品即可出厂。 FactoryMethod模式在一个抽象类中留下某个创建元件的抽象方法没有实作,其它与元件操作相关联的方法都先依赖于元件所定义的介面,而不是依赖于元件的实现,当您的成品中有一个或多个元件无法确定时,您先确定与这些元件的操作介面,然后用元件的抽象操作介面先完成其它的工作,元件的实作(实现)则推迟至实现元件介面的子类完成,一旦元件加入,即可完成您的成品。 再举一个例子,假设您要完成一个文件编辑器,您希望这个编辑器可以适用于所有类型的档案编辑,例如RTF、DOC、TXT等等,尽管这些文件有着不同的格式,您先确定的是这些文件必然具备的一些操作介面,例如储存、开启、关闭等等,您用一个IDocument类型来进行操作,这么一来这个框架就无需考虑实际的储存、开启等细节是如何进行的。 以UML类别图来表现以下的概念: AbstractEditor中的createDocument()方法是个抽象方法,因为框架不知道您将实现一个什么类型的文件,这个抽象方法将推迟至继承AbstractEditor的子类中实现。 这个架构可用以下简单的示意程式来作示范,当中实现了一个RTFDocument,虽然在AbstractEditor中并不知道我们会套用这个RTFDocument,但您可以看到,透过多型操作,您的框架可以进行对文件的相关操作。 ∙AbstractEditor.java publicabstractclassAbstractEditor{ privateIDocumentdocument; publicabstractIDocumentcreateDocument(); publicvoidnewDocument(){ document=createDocument(); document.open(); } publicvoidsaveDocument(){ if(document! =null) document.save(); } publicvoidcloseDocument(){ if(document! =null) document.close(); } } ∙IDocument.java publicinterfaceIDocument{ publicvoidopen(); publicvoidsave(); publicvoidclose(); } ∙RTFEditor.java publicclassRTFEditorextendsAbstractEditor{ publicIDocumentcreateDocument(){ returnnewRTFDocument(); } } ∙RTFDocument.java publicclassRTFDocumentimplementsIDocument{ publicRTFDocument(){ System.out.println("建立RTF文件"); } publicvoidopen(){ System.out.println("开启文件"); } publicvoidsave(){ System.out.println("储存文件"); } publicvoidclose(){ System.out.println("关闭文件"); } } 将FactoryMethod的结构绘出如下
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 设计 模式
![提示](https://static.bdocx.com/images/bang_tan.gif)