23种设计模式(9):访问者模式
- 格式:pdf
- 大小:1.00 MB
- 文档页数:7
常见的⼆⼗三种设计模式按照⽬的来分,设计模式可以分为创建型模式、结构型模式和⾏为型模式。
创建型模式⽤来处理对象的创建过程;结构型模式⽤来处理类或者对象的组合;⾏为型模式⽤来对类或对象怎样交互和怎样分配职责进⾏描述。
创建型模式⽤来处理对象的创建过程,共以下五种:单例模式(Singleton Pattern)能避免同⼀对象被反复实例化。
⽐如说,访问数据库的连接对象就⽐普通对象实例化的时间要长;WCF中,维护服务器端远程对象的创建等,这类情况,很有必要⽤单例模式进⾏处理对象的实例化。
简单⼯⼚模式通过在⼯⼚类中进⾏判断,然后创建需要的功能类。
优点:不必使⽤具体的功能类去创建该类的实例。
缺点:新增⼀个功能类就需要在⼯⼚类中增加⼀个判断。
⼯⼚⽅法模式(Factory Method Pattern)把简单⼯⼚模式中的⼯⼚类,做了进⼀步的抽象为接⼝或抽象类,给各个功能创建⼀个对应的⼯⼚类,然后在这个⼯⼚类⾥⾯去创建对应的实例。
缺点:当新增⼀个功能类,就需要创建对于的⼯⼚类,相⽐简单⼯⼚模式,免去了判断创建那个具体实例,但会创建过多的类,还不如策略模式。
抽象⼯⼚模式(Abstract Factory Pattern)使⽤该功能类的功能类,利⽤抽象⼯⼚去创建该功能类的实例。
这样的好处在于尽可能的避免去创建功能的实例。
更⽜逼的做法就是使⽤反射去创建这个功能类的实例,在调⽤端就⼀点都不需要知道要去实例化那个具体的功能类。
这当然不是抽象⼯⼚模式独有的。
建造者模式(Builder Pattern)每个对象都具备⾃⼰的功能,但是,它们的创建⽅式却是⼀样的。
这个时候就需要中间这个建造者类来负责功能对象实例的创建。
在调⽤端只需调⽤特定的⽅法即可。
这个和策略模式有点类似。
原型模式(Prototype Pattern)创建好了⼀个实例,然后⽤这个实例,通过克隆⽅式创建另⼀个同类型的实例,⽽不必关⼼这个新实例是如何创建的。
原型模式使⽤时需要注意浅拷贝与深拷贝的问题。
设计模式:访问者(Visitor)模式设计模式:访问者(Visitor)模式⼀、前⾔什么叫做访问,如果⼤家学过数据结构,对于这点就很清晰了,遍历就是访问的⼀般形式,单独读取⼀个元素进⾏相应的处理也叫作访问,读取到想要查看的内容+对其进⾏处理就叫做访问,那么我们平常是怎么访问的,基本上就是直接拿着需要访问的地址(引⽤)来读写内存就可以了。
为什么还要有⼀个访问者模式呢,这就要放到OOP之中了,在⾯向对象编程的思想中,我们使⽤类来组织属性,以及对属性的操作,那么我们理所当然的将访问操作放到了类的内部,这样看起来没问题,但是当我们想要使⽤另⼀种遍历⽅式要怎么办呢,我们必须将这个类进⾏修改,这在设计模式中是⼤忌,在设计模式中就要保证,对扩展开放,对修改关闭的开闭原则。
因此,我们思考,可不可以将访问操作独⽴出来变成⼀个新的类,当我们需要增加访问操作的时候,直接增加新的类,原来的代码不需要任何的改变,如果可以这样做,那么我们的程序就是好的程序,因为可以扩展,符合开闭原则。
⽽访问者模式就是实现这个的,使得使⽤不同的访问⽅式都可以对某些元素进⾏访问。
⼆、代码Element 接⼝:1package zyr.dp.visitor;23public interface Element {45public abstract void accept(Visitor visitor);67 }Entry 类:45public abstract class Entry implements Element{6public abstract String getName();7public abstract int getSize();8public abstract void printList(String prefix);9public void printList(){10 printList("");11 }12public Entry add(Entry entry) throws RuntimeException{ 13throw new RuntimeException();14 }15public Iterator iterator() throws RuntimeException{16throw new RuntimeException();17 }18public String toString(){19return getName()+"<"+getSize()+">";20 }21 }File 类:1package zyr.dp.visitor;23public class File extends Entry {45private String name;6private int size;7public File(String name,int size){=name;9this.size=size;10 }11public String getName() {12return name;13 }1415public int getSize() {16return size;17 }1819public void printList(String prefix) {20 System.out.println(prefix+"/"+this);21 }22public void accept(Visitor visitor) {23 // System.out.println("开始访问⽂件:"+this);24 visitor.visit(this);25 // System.out.println("结束访问⽂件:"+this);26 // System.out.println();27 }2829 }Directory类:4import java.util.Iterator;56public class Directory extends Entry {78 String name;9 ArrayList entrys=new ArrayList();10public Directory(String name){=name;12 }13public String getName() {14return name;15 }1617public int getSize() {18int size=0;19 Iterator it=entrys.iterator();20while(it.hasNext()){21 size+=((Entry)it.next()).getSize();22 }23return size;24 }2526public Entry add(Entry entry) {27 entrys.add(entry);28return this;29 }3031public Iterator iterator() {32return entrys.iterator();33 }3435public void printList(String prefix) {36 System.out.println(prefix+"/"+this);37 Iterator it=entrys.iterator();38 Entry entry;39while(it.hasNext()){40 entry=(Entry)it.next();41 entry.printList(prefix+"/"+name);42 }43 }44public void accept(Visitor visitor) {45 // System.out.println("开始访问⽂件夹:"+this);46 visitor.visit(this);47 // System.out.println("结束访问⽂件夹:"+this);48 // System.out.println();49 }5051 }Visitor 类:1package zyr.dp.visitor;23public abstract class Visitor {45public abstract void visit(File file);6public abstract void visit(Directory directory);78 }ListVisitor类:5public class ListVisitor extends Visitor {67 String currentDir = "";8public void visit(File file) {9 System.out.println(currentDir+"/"+file);10 }1112public void visit(Directory directory) {13 System.out.println(currentDir+"/"+directory);14 String saveDir=currentDir;15 currentDir+=("/"+directory.getName());16 Iterator it=directory.iterator();17while(it.hasNext()){18 Entry entry=(Entry)it.next();19 entry.accept(this);20 }21 currentDir=saveDir;22 }2324 }FileVisitor 类:1package zyr.dp.visitor;23import java.util.ArrayList;4import java.util.Iterator;56public class FileVisitor extends Visitor {78 String currentDir = "";9 String suffix;10 ArrayList files=new ArrayList();1112public FileVisitor(String suffix){13this.suffix = suffix;14 }1516public void visit(File file) {17if(file.getName().endsWith(suffix)){18 // System.out.println(currentDir+"/"+file);19 files.add(currentDir+"/"+file);20 }21 }2223public void visit(Directory directory) {24 String saveDir=currentDir;25 currentDir+=("/"+directory.getName());26 Iterator it=directory.iterator();27while(it.hasNext()){28 Entry entry=(Entry)it.next();29 entry.accept(this);30 }31 currentDir=saveDir;32 }33 Iterator getFiles(){34return files.iterator();35 }3637 }Main类:56public class Main {78public static void main(String[] args) {910 Directory root=new Directory("根⽬录");1112 Directory life=new Directory("我的⽣活");13 File eat=new File("吃⽕锅.txt",100);14 File sleep=new File("睡觉.html",100);15 File study=new File("学习.txt",100);16 life.add(eat);17 life.add(sleep);18 life.add(study);1920 Directory work=new Directory("我的⼯作");21 File write=new File("写博客.doc",200);22 File paper=new File("写论⽂.html",200);23 File homework=new File("写家庭作业.docx",200);24 work.add(write);25 work.add(paper);26 work.add(homework);2728 Directory relax=new Directory("我的休闲");29 File music=new File("听听⾳乐.js",200);30 File walk=new File("出去转转.psd",200);31 relax.add(music);32 relax.add(walk);3334 Directory read=new Directory("我的阅读");35 File book=new File("学习书籍.psd",200);36 File novel=new File("娱乐⼩说.txt",200);37 read.add(book);38 read.add(novel);3940 root.add(life);41 root.add(work);42 root.add(relax);43 root.add(read);4445 root.accept(new ListVisitor());46 System.out.println("========================");47 FileVisitor visitor=new FileVisitor(".psd");48 root.accept(visitor);49 Iterator it = visitor.getFiles();50while(it.hasNext()){51 System.out.println(it.next());52 }5354 }5556 }运⾏结果:可以看到我们的运⾏结果第⼀个和使⽤Composite模式的结果⼀样,第⼆个是实现另⼀种⽅式的访问,只访问⽂件后缀为某⼀特定的内容的⽂件,结果也是正确的,并且为了说明我们的访问还可以保存下来访问的结果,我们使⽤了ArrayList⾃带的迭代器将保存到ArrayList中的结果输出出来,我们当然也可以直接在遍历的时候就输出出来,这个看我们的使⽤要求了。
23种基本的设计模式设计模式指的是在软件设计过程中,面对特定问题时能够重复使用的解决方案。
设计模式可帮助开发人员更完整、更高效地解决问题,并提高代码的可读性和可维护性。
在软件开发中,有23种基本的设计模式。
1. 单例模式(Singleton Pattern):确保一个类只有一个实例,并提供全局访问点。
2. 工厂模式(Factory Pattern):通过工厂方法创建对象,而不是直接实例化。
3. 抽象工厂模式(Abstract Factory Pattern):提供一个接口,用于创建相关或依赖对象的家族,而不需要指定具体类。
4. 建造者模式(Builder Pattern):将一个复杂对象的构造与它的表示分离,使得同样的构造过程可以创建不同的表示。
5. 原型模式(Prototype Pattern):通过复制已有对象来创建新对象,而不是通过实例化。
6. 适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的接口。
7. 桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们可以独立变化。
9. 装饰器模式(Decorator Pattern):动态地给一个对象添加额外的职责。
10. 外观模式(Facade Pattern):为子系统中的一组接口提供统一的接口,以提供更高级别的接口。
11. 享元模式(Flyweight Pattern):通过共享已存在的对象来减少内存占用。
12. 代理模式(Proxy Pattern):为其他对象提供一个代理以控制对这个对象的访问。
13. 模板方法模式(Template Method Pattern):定义一个操作中的算法骨架,而将一些步骤延迟到子类中。
14. 策略模式(Strategy Pattern):定义一系列的算法,将其逐个封装起来,并使它们可以相互替换。
15. 观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听其中一个主题对象。
23种设计模式及应用设计模式是指在软件设计过程中,针对常见问题的解决方案的经验总结。
它们提供了解决特定或常见问题的可重用方案,使得软件设计更加灵活、可扩展和可维护。
1. 创建型模式:- 单例模式:确保一个类只有一个实例,并提供全局访问点。
- 简单工厂模式:通过一个共同的接口创建不同的对象实例。
- 工厂方法模式:定义一个创建对象的接口,由子类决定具体创建哪个对象。
- 抽象工厂模式:提供一个创建一系列相关或互相依赖对象的接口。
- 建造者模式:将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
2. 结构型模式:- 适配器模式:将一个类的接口转换为客户端所期待的另一种接口。
- 桥接模式:将抽象部分与它的实现部分分离,使它们可以独立变化。
- 组合模式:将对象组合成树形结构以表示"整体-部分"的层次结构。
- 装饰器模式:动态地给对象添加额外的功能,避免继承带来的类膨胀问题。
- 外观模式:为子系统中一组接口提供一个一致的界面。
3. 行为型模式:- 策略模式:定义一系列算法,将它们封装起来,并使它们可以相互替换。
- 观察者模式:定义对象之间的依赖关系,当对象状态改变时自动通知依赖方。
- 模板方法模式:定义一个操作中的算法骨架,将一些步骤延迟到子类中实现。
- 命令模式:将一个请求封装成一个对象,从而使您可以用不同的请求参数化客户端对象。
- 状态模式:允许对象在其内部状态改变时改变其行为。
4. J2EE模式:- MVC模式:将应用程序划分为三个核心组件:模型、视图和控制器。
- 业务代表模式:将对业务对象的访问和业务逻辑从表示层分离出来。
- 数据访问对象模式:用于将业务逻辑和数据访问逻辑分离。
- 前端控制器模式:通过一个单一的入口点来处理应用程序的所有请求。
- 传输对象模式:用于在客户端和服务器之间传输数据。
5. 并发模式:- 线程池模式:创建一组预先初始化的线程对象来处理任务。
23种设计模式记忆口诀1.单例模式:独一无二,最重要。
2.工厂模式:制造者,无需说。
3.抽象工厂:一族产品,同根源。
4.建造者模式:一步一步,建造家。
5.原型模式:克隆专家,快捷法。
6.适配器模式:转换者,聪明智。
7.桥接模式:结构优化,灵活性。
8.装饰模式:装饰者,美化家。
9.组合模式:树形结构,组合家。
10.外观模式:微缩封装,简洁家。
11.享元模式:享元工厂,节省家。
12.代理模式:替身幕后,保护家。
13.模板方法:算法继承,不变家。
14.策略模式:行为封装,灵活家。
15.命令模式:命令者,有权家。
16.职责链模式:可扩展,级别性。
17.状态模式:状态管理,干净家。
18.观察者模式:被观察,自主家。
19.中介者模式:中介者,沟通家。
20.迭代器模式:循环选择,简化家。
21.访问者模式:动态添加,扩展家。
22.备忘录模式:状态备份,还原家。
23.解释器模式:解释语言,特殊家。
以上23种设计模式,为了更好地记忆,我把它们组合成了一个口诀:最重要的单例模式,工厂与抽象同皇冠。
建造渐进如养家,克隆是原型美化家。
适配器桥接转化家,组合成树形结构家。
装饰装扮美化家,微缩封装外观家。
享元共用节省家,代理替身保护家。
策略模式灵活家,命令者有权家。
职责链扩展级别性,状态干净管理家。
被观察自主家,中介者沟通家。
循环迭代简化家,访问者动态扩展家。
备忘录变化还原家,解释语言特殊家。
这个口诀是通过把每个模式的主要特点和功能用简洁的语句表达出来,然后通过排列组合的方式形成的。
相信这个口诀会让你更容易地记忆这23种设计模式,并且可以在以后的工作中灵活地运用它们。
架构师内功心法,23种设计模式中最为复杂的访问者模式详解访问者模式(Visitor Pattern)是一种将数据结构和数据操作分离的设计模式。
是指封装一些作用于某种数据结构中的各种元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
访问者模式被称为最复杂的设计模式,并且使用频率不高,设计模式的作者也评价为:大多情况下,你不需要使用访问者模式,但是一旦需要使用它时,那就真的需要使用了。
访问者模式的基本思想是,针对系统中拥有固定类型数的对象结构(元素),在其内提供一个accept()方法用来接受访问者对象的访问。
不同的访问者对同一元素的访问内容不同,使得相同的元素集合可以产生不同的数据结果。
accept()方法可以接收不同的访问者对象,然后在内部将自己(元素)转发到接收到的访问者对象的visit()方法内。
访问者内部对应类型的visit()方法就会得到回调执行,对元素进行操作。
也就是通过两次动态分发(第一次是对访问者的分发accept()方法,第二次是对元素的分发visit()方法),才最终将一个具体的元素传递到一个具体的访问者。
如此一来,就解耦了数据结构与操作,且数据操作不会改变元素状态。
一、访问者模式的应用场景访问者模式在生活场景中也是非常当多的,例如每年年底的KPI 考核,KPI考核标准是相对稳定的,但是参与KPI考核的员工可能每年都会发生变化,那么员工就是访问者。
我们平时去食堂或者餐厅吃饭,餐厅的菜单和就餐方式是相对稳定的,但是去餐厅就餐的人员是每天都在发生变化的,因此就餐人员就是访问者。
访问者模式的核心是,解耦数据结构与数据操作,使得对元素的操作具备优秀的扩展性。
可以通过扩展不同的数据操作类型(访问者)实现对相同元素的不同的操作。
简而言之就是对集合中的不同类型数据(类型数量稳定)进行多种操作,则使用访问者模式。
访问者模式的应用场景适用于以下几个场景:数据结构稳定,作用于数据结构的操作经常变化的场景;需要数据结构与数据操作呢分离的场景;需要对不同数据类型(元素)进行操作,而不使用分支判断具体类型的场景。
23种设计模式记忆口诀设计模式是软件开发中常见的解决方案模板,它们能够解决许多常见的设计问题。
为了帮助记忆23种设计模式,可以使用下面这个口诀来记忆:Creational Patterns(创建型模式):1. Singleton(单例模式):一个类能产生一个实例,全局访问。
2. Builder(建造者模式):分步骤创建复杂对象,易拓展。
3. Factory Method(工厂方法模式):子类决定实例化哪个对象。
4. Abstract Factory(抽象工厂模式):创建一组相关对象,不依赖具体类。
5. Prototype(原型模式):通过复制现有对象来创建新对象。
Structural Patterns(结构型模式):6. Adapter(适配器模式):将类的接口转换为客户端希望的接口。
7. Bridge(桥接模式):将抽象部分与实际部分分离。
将对象组合成树形结构来表示部分整体的层次结构。
9. Decorator(装饰器模式):动态地给对象添加功能。
10. Facade(外观模式):提供一个统一的接口,简化客户端使用。
11. Flyweight(享元模式):共享细粒度对象,减少内存使用。
12. Proxy(代理模式):控制对其他对象的访问。
Behavioral Patterns(行为型模式):13. Chain Of Responsibility(责任链模式):将请求的发送者和接收者解耦,多个对象都可能处理请求。
将请求封装成对象,可以用参数化方式处理。
15. Iterator(迭代器模式):提供一种遍历集合的统一接口。
16. Mediator(中介者模式):将多个对象之间的复杂关系解耦。
17. Memento(备忘录模式):将对象的状态保存起来,以后可以恢复。
18. Observer(观察者模式):当一个对象改变状态时,依赖它的对象都会收到通知。
19. State(状态模式):对象的行为随状态的改变而改变。
面向对象设计的23个设计模式详解面向对象设计是一种广泛应用于软件开发的思想,其核心在于将数据和操作封装在一起形成对象,并通过各种方式进行交互和组合,从而实现复杂的功能。
在这一过程中,设计模式起到了非常重要的作用,可以有效地提高代码的可读性、可维护性和可扩展性。
本文将对23种常见的设计模式进行详解。
一、创建型模式1.简单工厂模式简单工厂模式属于创建型模式,其目的是提供一个工厂类,使得创建对象的过程更加简单。
在这种模式中,使用者只需要提供所需对象的参数,而无需关心对象的具体实现细节。
简单工厂模式适合于对象创建过程较为简单的情况。
2.工厂方法模式工厂方法模式是简单工厂模式的进一步扩展,其核心在于将工厂类进行接口抽象化,使得不同的工厂类可以创建不同的对象实例。
工厂方法模式适合于对象创建过程较为复杂的情况。
它可以为工厂类添加新的产品类型,而不会影响原有的代码。
3.抽象工厂模式抽象工厂模式是工厂方法模式的进一步扩展,其目的是提供一个可以创建一系列相关或者独立的对象的接口。
在抽象工厂模式中,使用者只需要关心所需对象组合的类型,而无需关注对象的具体实现过程。
4.建造者模式建造者模式也是一种创建型模式,其目的在于将复杂对象分解为多个简单的部分,并将其组装起来形成复杂对象实例。
在建造者模式中,使用者只需要关注所需对象以及它们的组合方式,而无需关心对象的具体实现过程。
5.原型模式原型模式是一种基于克隆的创建型模式,其核心在于通过复制现有的对象实例来创建新的对象。
在原型模式中,对象实例的创建过程与对象所包含的状态密切相关。
原型模式适合于创建复杂对象实例,且这些对象实例之间是相对独立的情况。
二、结构型模式6.适配器模式适配器模式是一种结构型模式,其目的在于将一个类的接口转换为另一个类所能使用的接口。
在适配器模式中,使用者可以通过不同的适配器实现对象之间的互相调用。
7.桥接模式桥接模式是一种结构型模式,其目的在于将抽象部分与实现部分相互分离,从而使得两者可以独立变化。
23种设计模式及其应⽤场景设计模式主要分三个类型:创建型、结构型和⾏为型。
其中创建型有:⼀、Singleton,单例模式:保证⼀个类只有⼀个实例,并提供⼀个访问它的全局访问点;应⽤场景:⼀个⽆状态的类使⽤单例模式节省内存资源。
⼆、Abstract Factory,抽象⼯⼚:提供⼀个创建⼀系列相关或相互依赖对象的接⼝,⽽⽆须指定它们的具体类。
应⽤场景:⼀系列相互依赖的对象有不同的具体实现。
提供⼀种“封装机制”来避免客户程序和这种“多系列具体对象创建⼯作”的紧耦合。
三、Factory Method,⼯⼚⽅法:定义⼀个⽤于创建对象的接⼝,让⼦类决定实例化哪⼀个类,Factory Method使⼀个类的实例化延迟到了⼦类。
应⽤场景:由于需求的变化,⼀个类的⼦类经常⾯临着剧烈的变化,但他却拥有⽐较稳定的接⼝。
使⽤⼀种封装机制来“隔离这种易变对象的变化”,⼯⼚⽅法定义⼀个⽤于创建对象的接⼝,让⼦类来确定创建哪⼀个具体类的对象,将对象的实例化延迟。
四、Builder,建造模式:将⼀个复杂对象的构建与他的表⽰相分离,使得同样的构建过程可以创建不同的表⽰。
应⽤场景:⼀个类的各个组成部分的具体实现类或者算法经常⾯临着变化,但是将他们组合在⼀起的算法却相对稳定。
提供⼀种封装机制将稳定的组合算法于易变的各个组成部分隔离开来。
五、Prototype,原型模式:⽤原型实例指定创建对象的种类,并且通过拷贝这些原型来创建新的对象。
应⽤场景:⽤new创建⼀个对象需要⾮常繁琐的数据准备或者权限⾏为型有:六、Iterator,迭代器模式:提供⼀个⽅法顺序访问⼀个聚合对象的各个元素,⽽⼜不需要暴露该对象的内部表⽰。
应⽤场景:迭代。
七、Observer,观察者模式:定义对象间⼀对多的依赖关系,当⼀个对象的状态发⽣改变时,所有依赖于它的对象都得到通知⾃动更新。
应⽤场景:某个实例的变化将影响其他多个对象。
⼋、Template Method,模板⽅法:定义⼀个操作中的算法的⾻架,⽽将⼀些步骤延迟到⼦类中,TemplateMethod使得⼦类可以不改变⼀个算法的结构即可以重定义该算法的某些特定步骤。
23种设计模式记忆口诀
1.单例模式:唯一实例化,静态访问,线程不安全
2. 工厂方法模式:子类实现,工厂创建,扩展性强
3. 抽象工厂模式:创建一族产品,接口约束,扩展性强
4. 建造者模式:组合复杂对象,分步骤构建,灵活性高
5. 原型模式:克隆对象,避免重复创建,效率高
6. 适配器模式:兼容接口不同,类似转换器,易扩展
7. 桥接模式:抽象与实现分离,解耦合,易扩展
8. 装饰器模式:动态增强对象功能,不影响原有对象,易扩展
9. 组合模式:层次结构,统一访问,易扩展
10. 外观模式:简化复杂系统调用,易使用,易扩展
11. 享元模式:共享资源,避免重复创建,效率高
12. 代理模式:增强对象功能,控制对象访问,易扩展
13. 责任链模式:多个对象处理请求,自动传递,易扩展
14. 命令模式:将请求封装成对象,易扩展,易记录日志
15. 解释器模式:解释语言,易扩展,易维护
16. 迭代器模式:遍历集合,统一访问,易扩展
17. 中介者模式:分离对象间交互,降低耦合,易扩展
18. 观察者模式:对象状态改变,通知观察者,易扩展
19. 备忘录模式:保存对象状态,易恢复,易扩展
20. 状态模式:对象状态改变,自动改变行为,易扩展
21. 策略模式:选择不同策略,易切换,易扩展
22. 模板方法模式:定义操作流程,易扩展,易维护
23. 访问者模式:统一访问集合中对象,易扩展,易维护。