1.设计模式...........................................................................................................................................21.1创建型模式.............................................................................................................................31.1.1工厂方法......................................................................................................................31.1.2抽象工厂......................................................................................................................51.1.3建造者模式..................................................................................................................91.1.4单态模式....................................................................................................................121.1.5原型模式....................................................................................................................141.2结构型模式...........................................................................................................................161.2.1适配器模式................................................................................................................161.2.2桥接模式....................................................................................................................181.2.3组合模式....................................................................................................................211.2.4装饰模式....................................................................................................................251.2.5外观模式....................................................................................................................271.2.6享元模式....................................................................................................................311.2.7代理模式....................................................................................................................331.3行为型模式...........................................................................................................................361.3.1责任链模式................................................................................................................361.3.2命令模式....................................................................................................................391.3.3解释器模式................................................................................................................421.3.4迭代器模式................................................................................................................441.3.5中介者模式................................................................................................................481.3.6备忘录模式................................................................................................................511.3.7观察者模式................................................................................................................531.3.8状态模式....................................................................................................................571.3.9策略模式....................................................................................................................601.3.10模板方法..................................................................................................................621.3.11访问者模式.............................................................................................................1Java设计模式(疯狂Java联盟版)1.设计模式(超级详细)
内容简介有感于设计模式在日常开发中的重要性,同时笔者也自觉对设计模式小有心得,故笔者*写二十三种设计模式的简单例子、并整理二十三种设计模式的理论部分,综合汇总成这份Java设计模式(疯狂J*va联盟版),希望对大家有所帮助。
本份帮助文档主要是为了向读者介绍二十三种设计模式,包括模式的描述,适用性,模*的组成部分,并附带有简单的例
子和类*,目的是为了让读*了解二十三种*计模式,并能方便的查阅各种设计模*的用法及注意点。
所附的例子非常简单,慢慢的引导读者从浅到深了解设计模式,并能从中享受设计的乐趣。
由于每个人对设计*式的理解都不尽一致,因此,可能本文档的例子*有不恰当的地方,还望各位读者指出不恰当的地方。
欢迎登录疯狂J*va联盟进行技术交流,疯狂Java联盟的论坛宗旨是:
所有的技术发帖,均有回复。
疯狂Java联盟网址:http://www.crazyit.org
笔者简介笔者曾师从李刚老师学习Java,现居广州。对Java软件开发、各种Java开源技术都非常感兴趣,曾参与开发、主持*发过大
量Java、JavaEE项目,对Java、Java*E项目有一定认识*见解。欢迎大家与笔者就Java、JavaEE相*方面进行技术交流。
笔者现为疯狂Jav*联盟的总版主(论坛ID:杨恩雄),也希望通过该平台与大家分享Java、JavaEE技术、*得。
本人邮箱:yangenxiong@163.com
声明本文档编写、制作过程中得到了疯狂Java联盟、以及笔者学习工作过程大量朋友的支持,大家都抱着一个目的:为国内软件软件开发事业作出绵薄贡献。
我们在此郑重宣布,本*档遵循Apache2.0协议。在完整保留全部文本(包括本版权页),并且不违反Apache2.0协议的前提
下,允许和鼓励任何人进行全文转载及推广,我们放弃除署名权外的一切权利。
2Java设计模式(疯狂Java联盟版)1.1创建型模式
AbstractFactory(抽象工厂)FactoryMethod(工厂方法)Singleton(单态模式)Builder(建造者模式)Protot*pe*原型模式)1.1.1工厂方法
*义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类的实例*延迟到其子类。
适用性1.当一个类不知道它所必须创建的对象的类的时候。2.当一个类希望由它的子类来指定它所创建的对象的时候。
3.当*将创建对象的职责委托给多个帮助*类中的某一个,并且*希望将哪一个帮助子类是代理者这一信息局部化的时候。
参与者1.Product
定义工厂方法所创建的对象的接口。2.ConcreteProduct实现Product接口。
3.Creator
声明工厂方法,该方法返回一个Product类型的对象*
Creator也可以定义一个工厂方法的缺省实现,它返回一个缺省的ConcreteProduct对象。
可以调用工厂方法以创建一个Product对象。
4.ConcreteCreator
重定义工厂方法以返回一个ConcreteProduct实例。
类图3Java设计模式(疯狂Java联盟版)例子*roductpublicinterfaceWork{
voiddoWork();}
ConcreteProductpublicclassStudentWorkimplementsWork{
publicvoiddoWork(){
System.out.println(\"学生*作业!\");}}
publicclassTeacherWorkimplementsWork{
publicvoiddoWork(){
System.out.println(\"老师审批作业!\");}}
CreatorpublicinterfaceIWorkFactory{
Workget*ork();}
Concre*eCreatorpu*licclassStudentWorkFactoryimplementsIWorkFactory{
4Java设计模式(疯狂Java联盟版)publicWorkgetWork(){
*eturnnewStudentWork();}}
publicclassTeacherWorkFactoryimplementsIWorkFactory{
publicWorkgetWork(){
returnnewTeacherWork();}}
TestpublicclassTest{
publicstaticvoidm*in(Strin*[]args){
IWorkFactorystudentWorkFactory=newStudentWorkFactory();studentWorkFactory.getWork().d*Work();
IWorkFactoryteacherWorkFactory*newTeacherWorkFactory();teacherWorkFactory.g*tWork().*oWork();}}
result学生做作业!老师审批作业!
1.1.2抽象工厂
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
适用性1.一个系统要于它的*品的创建、组合和表示时。2.一个系统要由多个产品系列中的一个来配置时。
3.当你要强调一系列相关的产品对象的设计以便进行联合使用时*4*当你提供一个产品类库,而只想显示它们*接口而不是实现时。
5Java设计模式(疯狂Java联盟版)参与者1.Ab*tractFactory
声明一个创建抽象产品对象的操作接口。2.ConcreteFactory
实现创建具体产品对象的操作。*.AbstractProduct
为一类产品对象声明一个接口。
4.ConcreteProdu*t
定义一个将被相应的具体工厂创建的产品*象。实现*bstractProduct接口。
5.Client
仅使用由AbstractFactory和AbstractProduc*类声明的接口
类图例子*bstractFactorypublicinterfaceIAn*malFactory{
ICatcreateCat();IDogcre*teDog();}
ConcreteFactory6Java设计模式(疯狂Java联盟版)p*blicclassBlackAnimalFactoryimplem*ntsIAnimalFactory{
publicICatcreateCat(){
retur*newBlackCat();}
publicIDogcreateDog(){
returnnewBlackDog();}}
publicclassWhiteAnimalFac*oryimp*ementsIAnimalFactory{
publicICatcreateCat(){
returnnewWhiteCat();}
publicIDogcre*teDog(){
returnnewWhiteDog();}}
Abstrac*ProductpublicinterfaceICat{
voideat();}
publicinterfaceIDog{
voideat();}
Concrete*roductpublicclassBlack*atimplementsICat{
publicvoideat(){
System.out.println(\"Thebl*ckcatiseating!\");}}
7Java设计模式(疯狂Java联盟版)publicclassWhiteCatimplements*Cat{
publicvoideat(){
Sy*tem.out.prin*ln(\"Thew*itecatiseating!*);}}
publicclassBlackDogimplementsIDog{
publicvoideat(){
System.out.println(\"Theblackdogiseating\");}}
publicclassWhiteDogimplementsIDog{
publicvoideat(){
System.out.println(\"Thewhitedogiseat*ng!\");}}
Clientpublicstaticvoidmain(String[]args){
IAnimalFactoryblackAnimalFa*tory=newBlackAnimalFactory();ICatblackCat=blackAnimalFactory.createCat();blackCat.eat();
IDogblackD*g=blackAnimalFactory.createDog();blackDog.eat();
IAnimalFactorywhiteAnimalF*ctory=newWhiteAnimalFactory();ICatwhiteCat=whiteAnimalFactory.createCat();whiteCat.eat();
IDog*hiteDog=whiteAnimalFactory.createDog();whiteDog.eat();}
res*ltThebla*kcatiseating!Th*blackdogiseatin*!Thewhitecatiseating!
8Java设计模式(疯狂Java联盟版)Thewhitedogis*ating!
1.1.3建造者模式
将一个复杂对象的构*与它的表示分离,使*同样的构建过程可以创建不同的表示。
适用性1.当创建复杂对象的算法应该于该对象的组成部分以及它们的装配方式时。
*.当构造过程必须允*被构造的对象有不同*表示时。
参与者1.Builder
为创建一个Product对象的各个部件指定抽象接口。2.ConcreteBuilder
实现Buil*er的接口以构造和装配该产品的各个部件。定义并明确它所创建的表示*提供一个检索产品的接口。3.Director
构造一个使用Builder接口的对象。
4.Product
表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。
包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
类图9Java设计模式(疯狂Java联盟版)例子Buil*erpublicinterfacePersonBuilder{
voidbuildHead();v*idbuildBody();voidbuildFoot()*PersonbuildPerson();}
ConcreteBuilderpublicclassManBuilderimplementsPersonB*ilder{
Personperson;
publicManBuilder(){
person=ne*Man();}
publ*cvoidbuild*ody(){
perso*.setBody(\"建造男人的身体\");
10Java设计模式(疯狂Java联盟版)}
publicvoidbuildFoot(){
person.setFo*t(\"建造男人的脚\");}
publicvoidbuildHead(){
pers*n.setHead(\"建造*人的头\");}
*ublicPersonbuildPerson(){
retur*person;}}
Dir*ctorpublicclassPersonDirec*or{
publicPersonconstructPerson(PersonBuilderpb){
pb.buildHead();pb.buildBody();pb.buildFoot();
returnpb.buildPerson();}}
ProductpublicclassPerson{
privateStringhead;privateStringbody;privateStringfoot;publicStringgetH*ad(){
returnhead;}
publicvoidsetHead(Stringhea*){
this.head=head;}
publicStringgetBody(){
11Java设计模式(疯狂Java联盟版)returnbody;}
publicvoidsetBody(Stringbody){
this.b*dy=body;}
publicStringgetFoot(){
returnfoot;}
publicvoidsetFoot(Stringfoot){
t*is.foot=foot;}}
publicclassManextendsPerson{}
Testpubl*cclassTest{
publicstaticvoidmain(String[]ar*s){
PersonDirectorpd=newPersonDirector();
Personperson=pd.constructPerson(newManBuilder());System*out.println(person.getBody());System.out.println(person.getFoot());System.out.println(person.getHead());}}
result建造男人*身体建造男*的脚建造男人的头
1.1.4单态模式
保证一个类仅有一个实例,*提供一个访问它的全局访*点。
适用性1.当类只能有一个*例而且客户可以从一个众所周知的访问点访问它时。
12Java设计模式(疯狂Java联盟版)2.当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
参与者Singleton
定义一个Instance操作,允许客户访问它的唯一实例。Instance是一个类操作。
可能负*创建它自己的唯一实例。
类图例子SingletonpublicclassSingleton{
privatestaticSingletonsing;privateSingleton(){}
publicst*ticSingletonget*nstance(){
if(sing==null){
sing=newSingleto*();}
returnsing;}}
TestpublicclassTest{
publicstaticvoid*ain(*tring[]args){
Singletonsing=Singleton.getInstance();Singletonsi*g2=Singleton.getI*stance();
System.out.println(sing);System.out.pr*ntln(sing2);}}
result13Java设计模式(疯狂Java联盟版)singleton.Singleton@1c78e57singleton.Singleton@1c78e57
1.1.5原型模式
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
适用性1.当一个系统应该于它的产品创*、构成和表示时。2.当要实例化的类是在运行时刻指定时,例如,通过动态装载。3.为了避免创建一个与产品类层次平行的工厂*层次时。4.当一个类的实例只能有几个不同状态组合中的一种时。
建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
参与者1.Prototype
声明一个克隆自身的接口。2.ConcretePrototype
实现一个克隆自身的操作。
3.Client
让一个原型克*自身从而创建一个新的对象。
类图例子Prototype14Java设计模式(疯狂Java联盟版)publicclassPrototypeimplementsCloneable{
privateStringname;
publicvoidsetName(Stringname){
this.name=name;}
publicStringgetName(){
returnthis.name;}
publicObjectclone(){
try{
returnsuper.clone();}catch(Exceptione){
e.printStackTrace();returnnull;}}}
ConcretePrototypepubl*cclassConcretePrototypeextend*Prototype{
publicConcretePrototype(Stringname){
setName(name);}}
Clientpublicclas*Test{
publicstaticvoidmain(String[]args){
Prototypepro=newConcretePrototy*e(\"prototype\");Prototypepro2=(Prototype)pro.clone();*ystem.out.println(pro.getName()*;System.out.println(pro2.getName());}}
resultprototype
15Java设计模式(疯狂Java联盟版)prototype
1.2结构型模式
Adapter*适配器模式*Bridge(桥接模*)Composite(组合模式)Decorator(装*模式)Facade(外观模式)Flyweight(享元模式)Proxy(代理模式)1.2.1适配器模式
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口*兼容而不能一起工作的那*类可以一起工作。
适用性1.你想使*一个已经存在的类,而它的接口不符合你的需求。
2.你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那*接口
可能不一定兼容的类)协同工作。*.(仅适用于对象Adapter)你想使用一些已经存在的子类,但是不可能对每一个都进行
子类化以匹配它们的接口。对象适配器可以适配它的父类接口。
参与者1.Target
定义Client使用的与特定领域相关的接口。2.Client
与符合Target接口的对象协同。
3.Adapt*e
定义一个已经存在的接口,这个接口需要适配。4.Adapter
对Adaptee的接口与Target接口进行适配
16Java设计模式(疯狂Java联盟版)类图例子TargetpublicinterfaceTarget{
voidadapteeMethod();voidadapterMethod();}
AdapteepublicclassAdaptee{
publicvoidadapteeMethod(){
Syste*.out.p*intln(\"Adapteemethod!\");}}
Adapt*rpublicclas*Adapterimplement*Target{
privateAdap*eeadaptee;
publicAdapter(Adapteeadaptee){
this.adapte*=adaptee;}
publicvoidadapteeMethod(){
adaptee.adapteeMethod();
}
publicvoidadapterMethod(){
*ystem.out.println(\"Adaptermethod!\");}
17Java设计模式(疯狂Java联盟版)}
Clientpubliccla*sTest{
publicstati*voidmain(String[]args){
Targettarget=newAdapter(newAdaptee());tar*et.adapteeMethod();
target.adapterM*thod();}}
resultAdapteemethod!Adaptermethod!
1.2.2桥接模式
将抽象部分与它*实现部分分离,使它们都可以地变化。
适用性1.你不希望在抽*和它的实现部分之间有一个固定的绑定关系。
例如这种情况可能是因为,在程序运行时刻实现部分应可以*选择或者切换。
2.类的抽象以及它的实现都应该可以通*生成子类的方法加以扩充。这时Bridge模式使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
3.对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
4.正如在意图一节的第一个类图中所示的那样,有许多类要生成。这*一种类层次结构说明你必须将一个对象分解成两个部分。
5.*想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知*这一点。
参与者1.Abstraction
定义抽象类的接口。
18Java设计模式(疯狂Java联盟版)维护一个指向Implementor类型对象的指针。2.RefinedAbstraction
扩充由Abstraction定义的接口。
3.Implementor
定义实现类的接口,该接口不一定要与Ab*traction的接口完全一致。事实上这两个接口可以完全不同。
*般来讲,Implementor接口仅提供基本操作,而Abstraction则定义了基于这些基本操作的较高层次的操作。
4.ConcreteImplementor
*现Implementor接口并定义它的具体实现。
类图例子Abstr*ctionpublicabstractclassPerson{
privateClothingclothing;pr*vateStringtype;
publicClothinggetClothing(){
returnclothing;}
publi*voidsetClothing(){
this.clothing=*lothingFactory.getClothing();}
19Java设计模式(疯狂Java联盟版)publicvoidsetType(Stringtype){
t*is.type=type;}
publicStringgetType(){
returnthis.ty*e;}
publicabstractvoiddress();}
RefinedAbstractionpublicclassManextends*erson{
publicMan(){
setType(\"男人\");}
publicvoiddress(){
Clothingclothing=get*lothing();clothing.personDressCloth(this);}}
publicclassLadyextendsPerson{
publicLady(){
setTyp*(\"女人\");}
publicvoiddress(){
Cloth*ngclothing=getClothing();c*othing.personDressCloth(this);}}
Implemento*publicabstractclassClothing{
publicabstractvoidpersonDressC*oth(*ersonperson);}
ConcreteImplemento*publicclass*ack*textendsClothing{
20Java设计模式(疯狂Java联盟版)publicvoidpersonDressCloth(Personperson){
System.out.println(person.getType()+\"穿马甲\");}}
publiccl*ssTrouserextendsClothing{
publicvoidpersonDressCloth(Personperson){
System.ou*.println(*erson.getType()+\"穿裤子\");}}
TestpublicclassTe*t{
publics*aticvoidmain(String[]args){
Personman=newMan();Personlady=newLady();Clothingjacket=newJa*ket();Clot*ingtrouser=newTrouser();jacket.personDressCloth(man);trouser.personDressCloth(man);j*cket.personDressCloth(lady);trouser.personDressCloth(lady);}}
result男人穿马甲男人穿裤子女人穿马甲女人穿裤子
1.2.3组合模式
21Java设计模式(疯狂Java联盟版)将对象组合成树形结构以表示\"部分-整体\"的层次结构。\"Composite使得用户对单个对象和组合对*的使用具有一致性。\"
适用性1.你想表示对象的部分-整*层次结构。
2.你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
参与者1.Component
为组合中的对象声明接口。
在适当的情况下,实现所有类共有接口的缺省行为。声明一个接口用于访问和管理Component的子组件。
(可选)在递归结构中定义一个接口,用于访问一个父部件,并在合*的情况下实现它。
2.Leaf
在组合中表示叶节点对象,叶节点没有子节点。在组合中定义节点对象的行为。
3.Compos*te
定义有子部件的*些部件的行为。存储子部件。
在Component接口中实现与子部件有*的操作。4.Client
通过Component接*操纵组合部件的对象。
类图例子Component22Java设计模式(疯狂Java联盟版)p*blicabstractclassEmployer{
privateStringname;
publicvoidsetName(Stringname){
this.name=*ame;}
publicStringgetName(){
returnthis.name;}
publicabstractvoidadd(Employeremployer*;publicabstractvoiddelete(Employeremployer);publicListemployers;publicvoidprintInfo*){
System.out.println(name);}
*ublicListgetE*ployers(){
returnthis.employers;}}
LeafpublicclassProgrammerextendsEmployer{
publicProgrammer(Stringname){
setNam*(name);
employers=null;//程序员,表示没有下属了}
publicv*idadd(Employeremployer){}
publicvoiddelete(Employeremployer){}}
23Java设计模式(疯狂Java联盟版)publicclassPro*ectAssistantextendsEmployer{
publicProjectAss*stant(Stringname){
setName(name);
employers=*ull;//项目助理,表示没有下属了}
publicvoidadd(Employeremployer){}
publicvoiddelet*(Employeremployer){}}
CompositepublicclassProject*anagerextendsE*ployer{
publicProjectManager(Stringname){
setName(name);
employers=newA*rayList();}
publicvoidadd(Employeremployer){
employers.add(employer);}
publicvoiddelete(Emplo*eremployer){
employers.remove(employer);}}
Clie*tpubl*cclassTest{
publicst*ticvoidmain(String[]args){
Employerpm=newProjectManager(\"项目经理\");Emplo*erpa=newProjectAssistant(\"项目助理\");Employerprogra*mer1=newProgrammer(\"程序员一\");Employerprogrammer2=newProgrammer(\"程序员二\");
pm.add(pa);//为项目经理添加项目助理
pm.add(programmer2);//*项目经理*加程序员
24Java设计模式(疯狂Java联盟版)Listems=pm.getEm*loyers();for(Employerem:ems){
System.out.println(em.getNam*());}*}
result项目助理程序员二
1.2.4装饰模式
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模*相比生成子类更为*活。
适用性1.在不影响其他*象的情况下,以动态、透明的方式给单个对象添加职责。2.处理那些可以撤消的职责。
3.当不能采用生成子类的方法进行扩充时。
参与者1.Component
定义一个对象接口,可以给这些对象动态地添加职责。2.ConcreteComponent
定义一个对象,可以给这个对象添加一些职责。
3.Decorator
维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。
4.ConcreteDecorator向组件添加职责。
类图25Java设计模式(疯狂Java联盟版)例子ComponentpublicinterfacePerson{
voideat();}
ConcreteComponent*ublicclassM*nimplementsPerson{
publicvoideat(){
System.out.println(\"男人在吃\");
*
}
Decoratorpublicabstrac*classDecoratorimplementsPerso*{
protectedPersonperson*
publicvoidsetPerson(Personperson){
this.person=person;}
publicvoideat(){
person.eat();}}
ConcreteDec*ratorpubli*classManDecoratorAextendsDecorator{
26Java设计模式(疯狂Java联盟版)publicvoideat(){
super.eat();reEat();
Sy*tem.out.println(\"ManDecoratorA类\");}
publicvoidreEat(){
System.out.println(\"再吃一顿饭\");*}
publicclassManDecoratorBextendsDecorator*
publicvoideat(){
super.eat();
Syst*m.out.println(\"===============\");System.out.println(\"ManDecoratorB类\");}}
TestpublicclassTest{
publicst*ticvoidmain(Strin*[]args){
Manman=newMan();
ManDecoratorAmd1=newManDecoratorA();ManDecoratorBmd2=n*wManDecoratorB();
md1.setPerson(man);md2.setPerson(md1);md2.eat();}}
result男人在吃再吃一顿饭
ManDecoratorA类===============ManDecoratorB类
1.2.5外观模式
27Java设计模式(疯狂Java联盟版)为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这*子系统更加容易使用。
适用性1.当你要为一个*杂子系统提供一个简单接口时。子系统往往因为不断演化而变得越来越
复杂。大多数模式使用时都会产生更多更小的类。这使得子系统更具可重用性,也更容
易对子系统进行定制,但这也给*些不需要定制子系统的用户带来一些使用上的困难。
Fa*ade可以提供一个简单的缺省视图,这一视图对大多数用户来说已经足*,而那些需
要更多的可定制性的用户可以越过facade层。2.客户程序与抽象类的实现部分之间存在着很大的依赖性。引入facade将这个子系统与客
户以及其他的子系统分离,可以提高子系统的性和可移植性。3.当你需要构建一个层次结构的子系统时,使用facade模式定义子系统中每层的入口点。
如果子系统之间是相互依赖的,你可以让它们仅通过facade进行通讯,从而简化了它们
之间的依赖关系。
参与者1.Facade
知道哪些子系统类负责处理请求。
将客户的请求代理给适当的子系统对象。
2.Subsystemclasses实现子系统的功能。
处理由Facade对象指派的任务。
没有facade的任何相关信息;即没有指向*acade的指针。
类图28Java设计模式(疯狂Java联盟版)例子Facadepubli*classFacade{
ServiceAs*;ServiceBsb;ServiceCsc;public
sasbsc}
Facade(){
=newS*rviceAImpl();=new*erviceBImpl();=newServiceCImpl();
publicvoidmethodA(){
sa.methodA();sb.methodB();}
publi*voidmethodB(){
s*.methodB();sc.methodC();}
publicvoidmethodC(){
sc.methodC();sa.methodA();}
29Java设计模式(疯狂Java联盟版)}
Subsystemclasse*public*lassServiceAImplimplementsServiceA{
publicvoidmethodA(){
System.out.println(\"这是服务A\");}}
publicclassServiceBImplimplementsServiceB{
publicvoidmethodB(){
System.out.println(\"这是服务B\");*}
publicclassServiceCImplimplementsServiceC{
publicvoidmethodC(){
System.out.println(\"这是服*C\");}}
TestpublicclassTest{
publicstaticvoi*main(String[]args){
ServiceAsa=newServiceAImpl();Ser*iceBsb=newServiceBImpl();
sa.metho*A();sb.methodB();
System.out.println(\"========\");//facade
Facadefacade=newFacade();facade.methodA();facade.methodB();}}
resu*t这是服务A
30Java设计模式(疯狂Java联盟版)这是*务B========这是服务A这是服务B这是服务B这是服务C
1.2.6享元模式
运用共享技术有效地支持大量细粒度的对象。
适用性当都具备下列情况时,使用Flyweight模式:1.一个应用程序使用了大量的*象。
2.完全由于使用大量的对象,造成很大的存储开销。3.对象*大多数状态都可变为外部状态。
4.如果删除对象的外部状态,那么可以*相对较少的共享对象取代很多组对象。
5.应用程序不依赖于对象标识。由于Flyweight对象可以被共享,对于*念上明显有别的对象,标识测试将返回真值。
参与者1.Flyweight
描述一个接口,通过这个接口flyweight可以接受并作用于外部状态。2.ConcreteFlyweight
实现Flyweight接口,并为内部状态(如果有的话)增加存储空间。
Concrete*lyweight对象必须是可共享的。它所存储的状态必须是内部的;即,它必须于ConcreteFlyweight对象的场景。
3.UnsharedConcreteFlyweigh*
并非所有的Flywe*ght子类都需要被共享。Flyweight接口使共享成为可能,但它并不强制共*。
在Flyweight对象结构的某些层次,UnsharedConcreteFlyweight对象通常将ConcreteFlyweight对象作为子节点。
4.Flyweigh*Factory
31Java设计模式(疯狂Java联盟版)创建并管理flywe*ght对象。
确保合理地共享flyweight。当用户请求一个flywei*ht时,Fl*weightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)。
类*例子Flyweightpublicint*rfaceFlyweight{
voida*tion(intarg);}
ConcreteFlyweightpublicclassFlyweightImplimplementsFlyweight{
publicvoidaction(intarg){
//T*DOAuto-genera*edmethodstubSystem.out.println(*参数值:\"+arg);}}
FlyweightFactorypublicclassFlyweigh*Factory{
privatestaticMapflyweights=newHashMap();publicFlyweightF*ctory(Stringarg){
flyweights.put(arg,newFlyweightImpl());}
publicstaticFlyweightgetFly*eight(Stringkey){
if(flyweights.get(key)==null){
flyweights.p*t(key,newFlyweightImpl());
32Java设计模式(疯狂Java联盟版)}
returnflyweights.get(key);}
publicstaticintg*tSize(){
retu*nflyweights.size();}}
TestpublicclassTest{
publicstaticv*idmain(String[]args){
//TODOAuto-generatedmethodstub
Flyweightfly1=Flyw*ightFact*ry.getFlyweight(*a\");fly1.action(1);
Flyweightfly*=FlyweightFactory.getF*yweight(\"a\");System.out.println(fly1==fly2);
Flyweightfl*3=FlyweightFactory.getFlywei*ht(\"b\");fly3.action(2);
Flyweightfly4=Flyweigh*Factory.getF*yweight(\"c\");fly4.action(3);
Flyweigh*fly5=FlyweightFactory.getFlyweight(\"d\");fly4.action(4);
System.out.println(FlyweightFactory.getSize())*}}
result参数值:1true
参数值:2*数值:3参数值:44
1.2.7代理模式
33Java设计模式(疯狂Java联盟版)为其他对象提供一种代理以控制对这个对象的访问。
适用性1.远程代理(RemoteProxy)为一个对象在不同的地址空间提供局部代表。2.虚*理(VirtualProxy)根据需*创建开销很大的对象。3.保护代理(ProtectionProxy)控制对原始对象的访问。
4.智能指引(SmartReference)取代了简单的指针,它在访问对象时执行一些附加操作。
参与者1.Proxy
保存一个引用使得代理可以访问实体。若RealSubject和Subject的接口相同,Proxy会引用Subject。
*供一个与Subject的接口相同的接口,这样代理就可以用来替代实体。控制对实体的*取,并可能负责创建和删除它。其他功能依赖于*理的类型:2.RemoteProxy负责对请求及其参数进行编码,并向不同地址空间中的实体发送已编码的请求。
*.VirtualProxy可以缓存实体的附加信息,以便延迟对它的访问。4.ProtectionProxy检查调用者是*具有实现一个请求所必需的访问权限。5.Subjec*
定义RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都*以使用Proxy。
6.RealSubject
*义Proxy所代表的实体。
类图例子Proxy34Java设计模式(疯狂Java联盟版)publicclassProxyObjectimplementsObject{
Objec*obj;
publicProxyObject(){
System.out.println(\"这是代理类\");o*j=newObjectImpl();}
publicvoidac*ion(){
System.out.p*intln(\"代理开始\");obj.action*);
System.out.println(*代理结束\");}}
SubjectpublicinterfaceObje*t{
voidaction();}
RealSubjectpublicclassObjectImplimplementsObject{
pu*licvoidaction(){
System.out.println(\"========\");System.out.println(\"========\");
System.out.pr*ntln(\"这是被代理的类\");System.out.println(\"========\");System.out.println(\"========\");}}
TestpublicclassTest{
publi*staticvoidmain(){
Objectob*=newProxyObject();obj.action();*}
result35Java设计模式(疯狂Java联盟版)这是代理类代理开始=========*======
这是被代理的类==============*=代理结束
1.3行为型模式
ChainofResponsibility(责任链模式)Command(命令模式)Interpreter(解释器模式)Iterator(迭代器*式)Mediator(中介者模式)Memento(备忘录模式)Observer(观察者模式)State(状*模式)Strategy(策略模式)TemplateMethod(模板方法)Vis*tor(访问者模式)1.3.1责任链模式
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一*链,
并*着这条链传递该请求,直到有一个对象处理它为止。这一模式的想法是,给多个对象处理一个请求的机会,从而解耦发送者和接受者.
适用性1.有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。2.你*在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。3.可处理一个请求的对象集合应被动态指定。
参与者36Java设计模式(疯狂Java联盟版)1.Handler
定义一个处理请求的接口。(可选)实现后继链。
2.ConcreteHandler处理它所负责的请*。可访问它的后继者。
如果可处理该*求,就处理*;否则将该请求转发给它的后继者。3.Client
向链上的具体处理者(ConcreteHandler)对象提交请求。
类图例子Hand*erpublicinterfaceRequestHandle{
voidhandleRequest(R*questrequest);}
ConcreteHandlerpublicclassHRRequestHandleimplementsRequestHandle{
publicvoidhandleRequest(Requestrequest){
if(requestinstanceofDimissionRequest){
System.out.println(\"要离职,人事审批!\");}
System.out.println(\"请求完*\");}}
37Java设计模式(疯狂Java联盟版)publicclassPMRequestHandleimplementsRequestHandle{
Req*estHandlerh;
publicPMRequestHandle(RequestHandle*h){
this.rh=rh;}
publicvoidhandle*equest(Requestrequest){
if(requestinstanceofAddMoneyRequest){
System.out.println(\"要加薪,项目经理审批!*);}else{
rh.handleRequest(request);}}}
publicclassTLRequestHandleimplementsRequestHandle{
RequestHandlerh;
publicTLRequestHandle(RequestHand*erh){
this.rh=rh;}
publicvoidhandleRequest(Requestrequest){
if(requestinstanceofLeaveRe*uest){
System.ou*.println(\"要请假,项目组长审批!\");}else{
rh.handleRequest(request);}}}
Clientpublic*lassTest{
publicstaticv*idmain(String[]args){
RequestHa*dlehr=*ewHRRequ*stHandle();Requ*stHandlepm=newP*RequestHandle(hr);RequestHandletl=newTLRequestHandle(pm);
38Java设计模式(疯狂Java联盟版)//teamleader处理离职请求
Requestrequest=newDimissionRequest()*tl.handleRequest(request);System.out.println(\"===========\");//teamleader处理加薪请求
request=newAddMoneyRequest();tl.handleRequ*st(request);System.out.println(\"========\");//项目经理上理辞职请求
requ*st=ne*Dimissio*Request();pm.handleRequest(request);}}
result要离职,人事审批!请求完毕=======*===
要加薪,项目经理审批!========
要离职,人事审批!请求完毕
1.3.2命令模式
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的*作。
适用性1.抽象出待执行的动作以参数化某对象。2.在不同的时刻指定、排列和执行请求。3.支持取消操作。
4.支持修改日志,这样当系统崩溃时,这*修改可以被重做一遍。5.用构建在原语操作上的高层操作构造一个系统。
参与者39Java设计模式(疯狂Java联盟版)1.Comma*d
声明执行操作的接口。
2.ConcreteCommand
将一个接收者对象绑定于一个动作。
调用接收者相应的操作,以实现Execute。3.Client
创建一个具体命令对象并设定它的接收者。4.Invoker
要求该命令执行这个请求。
5.Recei*er
知道如何实*与执行一个请求相关的操作。任何类都可能作为一个接收者。
类图例子Commandpublicabstractclass*ommand{
protecte*Receiverreceiver;publicCommand(Receiverre*eiver){
this.receiver=receiver;}
publicabstract*oidexecute();
40Java设计模式(疯狂Java联盟版)}
ConcreteCommandpublicclassCommandImplextendsComman*{
publicCommandImpl(Receiv*rreceiver){
super(receiver);}
pu*licvoid*xecute*){
receiver.request();}}
Invokerpubliccl*ssInvoker{
privateCommandcommand;
pub*icvoidsetCommand(Commandc*mmand){
this.command=command;}
publicvoidexecute*){
command.execute();}}
ReceiverpublicclassReceiver{
publicvoidreceive(){
S*stem.out.println(\"ThisisReceiveclass!\");}}
Testpubl*cclassTest{
pub*icstaticvoidmain*String[]args){
R*ceiverrec=newReceiver();
Commandcmd=n*wCommandImpl(rec);Invokeri=newInvoker();i.setCom*and(cmd);
41Java设计模式(疯狂Java联盟版)i.execut*();}}
resultThisisReceiveclass!
1.3.3解释器模式
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
适用性当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使
用解释器模式。而当存在*下情况时该模式效果最好:
1.该文法简单对于复杂的文法,文法的*层次变得庞大而无法管理。2.效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将它们转换成另一种形式。
参与者1.AbstractExpression(抽象表达式)
声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。2.TerminalExpression(终结符表达式)
实现与文法中的终结符相关联的解释操作。
一个句子中的每个终结符需要该类的一个实例。3.N*nterminalExpression(非终结符表达式)
为文法中的非终结符实现解释(Interpret)操作。4.Context(上下文)
包含解释器之外的一些全局信息。
5.Client(客户)
构建(或被给定)表示该文法定义的语言中*个特定的句子的抽象*法树。该抽象语法树由NonterminalExpression和TerminalExpression的实例装配而成。
调用解*操作。
类图42Java设计模式(疯狂Java联盟版)例子AbstractExpressionpu*licabstractclassExpression{
abstractvoidinterpret(Contextctx);}
ExpressionpublicclassAdvanceExpressio*extendsExpression{
voidinterpr*t(Contextctx){
System.out.println(\"这是高级解析器!\");}}
publicclassSimpleExpressionextendsExpressio*{
voidinterpret(*ontextctx){
System.out.pri*tln(\"这是普通解析器!\");}}
ContextpublicclassCo*text{
privateS*ringcontent;
43Java设计模式(疯狂Java联盟版)*rivateListlist=newArrayList();publicvoidsetContent(Stringcontent){
this.content=content;}
pu*licStringgetContent(){
returnthis.con*ent*}
publicvoidadd(Expressionep*){
list.add(eps);}
publicListgetList(){
returnlist;}}
TestpublicclassTest{
publicstaticvoidmain(String[]args){
Context*tx=newContext();ctx.*dd(newSimpleExpression());ctx.add(newAdvanceExpression());ctx.add(newSimpleExpression());
for*Expressioneps:ctx.getL*st()){
eps.interpret*ctx);}}}
res*lt*是普通解析器!这是高级解析器!*是普通解析器!
1.3.4迭代器模式
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
44Java设计模式(疯狂Java联盟版)适用性1.访问一个聚合对象的内容而无需暴露它的内部表示。2.支持对聚合对象的多种遍历。
3.为遍历不同的聚合结构提供一*统一的接口(即,支持多态迭代)。
参与者1.Iterator
迭代器定义访问和遍历元素的接口。2.ConcreteIterator
具*迭代器实现迭代器接口。对该聚合遍历时跟踪当前位置。3.Aggregate
聚合定义创建相应迭代器*象的接口。
4.ConcreteAggregate
具体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例.
类图例子IteratorpublicinterfaceIterator{
Objectnex*();
45Java设计模式(疯狂Java联盟版)voidfirst();voi*last();booleanhasNext();}
ConcreteIteratorpublicclassIteratorImplimplementsIt*rator{
privateListlist;privateintindex;
publicIte*atorImpl(Listlist*{
index=0;
this.list=list;}
publicvoidfirst(){
index=0;}
publ*cvoidlast(){
index=list.getSize();}
publicObjectnext(){
Objectobj=list.get(index);index++;ret*rnobj;}
publicbooleanhasNext(){
returnindex Iteratoriterator(); 46Java设计模式(疯狂Java联盟版)Objectget(intindex);int*etSize();voidadd(Objectob*);} ConcreteAggregatepublicclassListImplimplementsList{ privateObject[]list;privateintindex;privateintsize; publicListImpl(){ index=0;size=0; list=newObject[100];} publicIteratoriterator(){ returnnewIteratorImpl(this);} publicO*jectget(intindex){ returnlist[index];} publicintgetSize(){ returnthis.size;} publicvoidadd(Objectobj){ list[index++]=obj;size++;}} TestpublicclassTest{ publicstati*voidmain(String[]arg*){ 47Java设计模式(疯狂Java联盟版)Listlist=newListImpl();list.add(\"a\");list.add(\"b\");list.add(\"c\");//第一种迭代方式 Iteratorit=list.iterator();while(*t.ha*Next()){ S*stem.out.println(it.next());} Syst*m.out.println(\"=====\");//第二种迭代方式 for(inti=0;i resultabc=====abc 1.3.5中介者模式 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以地改变它们之间的交互。 适用性1.一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。 2.一个对象引用其他很多对象并且直接与这些对象通信,导致难以复*该对象。 3.想定制一个分布在多个类中的行为,*又不想生成太多的子类。 参与者48Java设计模式(疯狂Java联盟版)1.Mediator 中介者定义一个接口用于与各同事(Colleague)对象通信。2.ConcreteMediator 具*中介者通过协调各同事对象实现协作行为*了解并维护它的各个同事。 3.Colleagueclass 每一个同事类都知道它的中介者对象。 每一个同事对象在需与其他的同事通信的时候*与它的中介者通信 类图例子MediatorpublicabstractclassMediator{ publicabstractvoidnotice(Stringcontent);} ConcreteMediatorpublic*lassConcreteMediatore*tendsMediator{ privateColleagueAca;pri*ateColleagueBcb;publicConcreteMediator(){ ca=newColleagueA();cb=newCol*eagueB();} publicvoidno*ice(Stringcontent){ if(co*tent.equals(\"boss\")){ 49Java设计模式(疯狂Java联盟版)//老板来了,通知员工Aca*action(); } if(content.equals(\"client\")){ //客户来了,*知前台Bcb.action();}}} ColleagueclasspublicclassColleagueAextends*olleague{ publicvoidaction(*{ System.out.println(\"普通员工努力工作\");}* publicclassColleagueBextendsColleague{ publicvoidaction(){ System.out.println(\"前台注意了!\");}} TestpublicclassTest{ publicstaticvoidmain(String[]args){ Mediatormed=newConcr*teMediator();*/老板来了 med.notice(\"boss\"); //客户来* med.n*tice(\"client\");}} result普通员工努力工作前台注意了! 50Java设计模式(疯狂Java联盟版)1.3.6备忘录模式 在不破坏封装性*前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 适用性1.必须*存一个对象在某一个时刻的(部分)状态,这样以后需要时它才能恢复到先前的状态。 2.如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。 参与者1.Memento 备忘录存储原发器对象的内部状态。 2.Originator 原发器创建一个备忘录,用以记录当前时刻*的内部状态。使用备忘录恢复内部状态. 3.Caretaker 负责保存好备忘录。 不能对备忘录的内*进行操作或检查。 类图例子MementopublicclassMemento{ 51Java设计模式(疯狂Java联盟版)privateStringstate; publicMeme*to(Stringstate){ this.state=state;} publicStringgetState(){ *eturnstate;} publicvoidsetSt*te(Stringstate){ this.stat*=s*ate;}} Or*ginatorpublicclassOriginator{ privateStringstate;publicStringgetState(){ returnstate;} publicvoidsetState(Stringstate){ this.state=state;} *ublicMementocreateMemento(){ returnnewMemento(state);} p*blicvoidsetMemento(Mementomeme*to){ state=memento.ge*State();} p*blicvoidshowState(){ System.out.println(state);}} CaretakerpublicclassCaretaker{ 52Java设计模式(疯狂Java联盟版)p*ivateMementomemento;publicMementogetMemento(){ returnthis.memento;} publicvoidsetMemento(Mementomemento){ this.memento=memento;}} TestpublicclassTest{ publicstaticvoidmain(String[]args){ Originatororg=*ewOriginator();org*setState(\"开会中\"); C*retakerctk=newCa*etaker(); ctk.setMemento(org.createMemento());//将数据封装在Caretakeror*.setState(\"睡觉中\");org.sh*wState();*/显示 org.setMemento(ctk.getMemento());//将数据重新导入or*.showState();}} result睡觉中开会中 1.3.7观察者模式 定义对象间的一种一*多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 适用性1.当一个抽象模型有两个方面,其中一个方面依赖于另一方面。 将这二者封装*的对象中以使它们可以各自地改变和复用。 53Java设计模式(疯狂Java联盟版)2.当对一个对象的改变需要同时改变其它对象,而不知道具体*多少对象有待改变。 3.当一个对象必须通知其它对象,而它又不能假定其它对象是谁。 参与者1.Subject(目标) 目标知道它的观*者。可以有任意多个观察者观察同一个目标。提供注册和删除观察者对象的接口。 2.Obser*er(观察者) 为那些在目标发生改变时需获得*知的对象定义一个更新*口。3.ConcreteSubject(具体目标) 将有关状态存入各ConcreteObserver对象。 当它的状态发生改变时,向它的各个观察者发出通知。4.ConcreteObserver(具体观察者) 维护一个指向ConcreteSubject对象的引用。 存储有关状态,这些状态应与目标的状态保持一致。 实现Observer的更新接口*使自身状态与目标的状态保持一致 类*例子SubjectpublicabstractclassCitizen{ Java设计模式(疯狂Java联盟版)Listpo*s; Stringhelp=\"normal\"; publicvoidsetHelp(Stringhelp){ this.help=*elp;} publicStringgetHelp(){ returnthis.help;} abstractvoidsendMessage(Stringhelp);publicvoidsetPolicemen(){ t*is.pols=newArrayList();} publicvoidregister(*olicemanpol){ this.pols.add(pol);} publicvoidunRegister(Policemanpol){ this.pols.remove(pol);}} ObserverpublicinterfacePoliceman{ voidaction(Citizenci);} *oncreteSubjec*publicclassHua*gPuCitizenextendsCitiz*n{ publicHuangPuCitizen(P*licemanpol){ setPolicemen();register*pol);} publicvoidsendMessage(Stringhelp){ setHelp(h*lp); for(inti=0;i publicclassTianHeCitizenextendsCitizen{ publicTianHeCitizen(Policemanpol){ setPolicemen();re*ister(pol);} publicvoidsendM*ssage(Str*nghelp){ setHelp(help); for(i*ti=0;i ConcreteObserverpublicclas*HuangPuPolicemanimplementsPol*ceman{ publicvoidaction(Citizenci){ Stringhelp=ci.getHelp();if(help.equals(\"normal\")){ System.o*t.println(\"一切正常,不用出动\");} if(help.*quals(\"unnormal\"))* System.out.println(\"有犯罪行为,黄埔出动!\");}}} publicc*assTianHePolicemanimplementsPolicem*n{ publicvoidaction(Citizenci){ Stringhelp=*i.getHelp();if(help.equals(\"*ormal\")){ System.out.println(\"一切正常,不用出动\"); 56Java设计模式(疯狂Java联盟版)* if(help.equals(\"unnormal\")){ System.out.println(\"有犯罪行为,天河出动!\");}}} TestpublicclassTest{ publicst*ticvoidmain(String[]args){ PolicemanthPol=newTianHePoliceman();Pol*cemanhpPol=newHuangPuPoliceman(); Ci*izencitizen=newHuangPuCitizen(hpPol);citizen.sendMessage(\"unnormal\");citizen.sendMessage(\"normal\");System.out.println(\"===========\");citizen=newTianH*Citizen(thPol);citizen.sendMessage(\"normal\");citi*en.sendMessage(\"unnormal\");}} result有犯罪行为,黄埔出动!一切正常,不用出动======*==== 一切正常,不用出动 有犯罪行为,天河出动! 1.3.8状态模式 定义对象间*一种一对多的依赖关系,当一个对象的状态*生改变时,所*依赖于它的对象都得到通知并被自动更新。 适用性1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改*它的行为。 57Java设计模式(疯狂Java联盟版)2.一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。 这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。 State模式将每一个条件分支放入一个的类中。 这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而变化。 参与者1.Context 定义客户感兴趣的接口。 维护一个ConcreteState子类的实例,这个实例定义当前状态。2.State 定义一个接口以封装与Context的一个特定状态相关的行为。3.ConcreteStatesubclasses 每一子类实现一个与Context的一个状态*关的行为。 类图例子*ontextpu*licclassContext{ privateWeatherweather; publicvoi*setWeather(Weatherweather){ this.*eather=weather;} pu*licWeathergetWeather(){ returnthis.weather;} 58Java设计模式(疯狂Java联盟版)publicStringweatherMessage(){ returnw*ather.getWeather();}} StatepublicinterfaceWeath*r{ St*inggetWeather();} Concrete*tatesubclassespublicclassRainimplementsWeather{ publicStri*ggetWeather(){ return\"下雨\";}* publicclassSunshineimplementsWeather{ publicStr*nggetWeather(){ return\"阳光\";}* TestpublicclassTest{ publicstaticvoidmain(String[]args){ Contextctx1=newContext();ctx1.setWeather(newSunshine()); System.out.println(*tx1.weatherMessage()); System.*ut.println(\"===============\");Contextctx2=newContext();ctx2.setWeather(newRain()); S*stem.out.println(ctx2.weatherMessage());}} result59Java设计模式(疯狂Java联盟版)阳光 ===============下雨 1.3.9策略模式 定义一系列的算法,把它们*个个封装起来,并且使它们可相互替换。本模式使得算法可于使用它的客户而变化。 适用性1.许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。 2.需要使用一个算法的不同变体。 3.算法使用客户不应该知*的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。 4*一个类定义了多种行为,并且这些行为在这个类的操作中以*个条件语句的形式出现。 将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。 参与者1.Strategy 定义所有支持的算法的公共接口。Context使用这个接口来调用某ConcreteStrate*y定义的算法。 2.ConcreteStrategy 以S*rategy接口实现某具体算法。 *.Context 用一个ConcreteStrateg*对象来配置。维护一个对Strategy对象的引用。 可定义一个接口来让Stategy访问它的数据。 类图60Java设计模式(疯狂Java联盟版)例子Strategypublicabstra*tclassStrategy{ pu*licabstractvoidmethod();} ConcreteStrategypublicclass*trategyImplAextendsStrategy{ publicvoi*method(){ System.out.println(\"这是第一个实现\");}} publicclassStrategyImplBextendsStrategy{ publicvoidmethod(){ System.out.println(\"这是第二个实现\");}} publicclassStrategyImplCextendsStrategy{ publicvoidmethod(){ Syst*m.out.println(\"这是第三个实现\");}} Contextpub*icclassContext{ Strategystra; 61Java设计模式(疯狂Java联盟版)publicCont*xt(Strategystra){ this.stra=stra;} pub*icvoiddoMethod(){ stra*method();}} TestpublicclassTest{ publicstaticvoidmain(String[]ar*s){ Contextctx=newC*ntext(newStrategyImplA());ctx.doMethod(); ctx=newContext(new*trategyImplB());ctx.doMethod(); ctx=newContext(newStrategyImplC());ctx.doMethod();}} result这是第一个实现这是第二个实现这是第三个实现 1.3.10模板方法 定义*个操作中的算法的骨架,*将一些步骤延迟到子类中。 TemplateMethod使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 适用性1.一次性实现一个算法的不变的部分,并将可变的*为留给子类来实现。2.各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。 首先识别现有*码中的不同之处,并且将不同之处分离为新的操作。最后,用*个调用这些新的操作的模板方法来替换这些不同的代码。 62Java设计模式(疯狂Java联盟版)3.控制子类*展。 参与者1.AbstractClass 定义抽象的原语操作(primitiveoperation),具体的子类将重定义它们以实现一个算法的各步骤。 实现一个模板方法,定义一个算法的骨架。 该模板方法不仅调用原语操作,也调用定义在AbstractClass或其他对象中的操作。 *.ConcreteClass 实现*语操作以完成算法中与特定子类相关的步骤。 类图例子AbstractClasspublicabstractclassTemplate{ publicabstractvoidprint();publicvoidupdate(){ System.out.println(\"开始打印\");for(inti=0;i<10;i++){ print();}}} ConcreteClasspublicclassTemplateConcreteextendsTemplate{ @*verride publicvoidprint(){ 63Java设计模式(疯狂Java联盟版)System.out.println(\"这是子类的实现\");}} TestpublicclassTest{ pu*licstaticvoidmain(String[]args){ Te*platetemp=newTemplateConcrete();temp.update();}} result开始打印 这是子类的*现这是子类的实现这是子类的实现这是子类的实现这是子类的实现这是子类的实现这是子类的实现这*子类的实现这是子类的实现这是子类的实现 1.3.11访问者模式 表*一个作用于某对象结构中的各元素的操作。 它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 适用性1.一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操*。 2.需要对一个对象结构中的对象进行很多不同的并且不相关的操作,*你想避免让这些操作“污染”这些对象的类。 Visitor使得你可以将相关的操作集中起来定义在一个类中。 当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。 3.定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。 改变对象结构类需要重定义对所有访问者的接口,这可能*要很大的代价。 Java设计模式(疯狂Java联盟版)如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。 参与者1.Visitor 为该对象结构中ConcreteEle*ent的每一个类声明一个Visit操作。该操作的名字和特征标识了发送*isit请求给该访问者的那个类。这使得访问者可以确定正被访问元素*具体的类。这样访问者就可以通过该元素的特定接口直*访问它。 2.Concret*Visitor 实现每个由Visitor声明的操作。每个操作实现本算法的一部分,而该算法片断乃是对应于结构中对象的类。Concret*Visitor*该算法提供了上下文并存*它的局部状态。这一状态常常在遍历该结构的过程中累*结果。3.Element 定义一个Accept操作,它*一个访问者为参数。4.ConcreteElement 实现Accept操作,该操作以一个访问者为参数。 5.ObjectStru*ture能枚举它的元素。 *以提供一个高层的接口以允许该访问者访问它的元素。 可以是一个复合或是一个集合,如一个列表或一个无序集合。 类图例子VisitorpublicinterfaceVisitor{ 65Java设计模式(疯狂Java联盟版)publicvoidvisitString(StringElementstringE);publicvoidvisitFloat(FloatElementfloatE);publicvoidvisitCollection(Collectioncollection);} ConcreteVisitorpublicclassC*ncreteVisitorimplementsVisitor{ publicvoidvisitCollectio*(Collectioncolle*tion){ //TODOAuto-generatedmethodstub Iteratoriterator=collection.iterator();while(iterator.hasNext()){ Objecto=iterato*.next();if(oin*tanceofVisitable){ (*Visitable)o).accept(this);}}} publicvoidvisitFloat(FloatElementfloatE){ System.out.println(floatE.getFe*));} publicvoidvisitString(StringElementstringE){ System.out.println(stringE.getSe());}} ElementpublicinterfaceVisitabl*{ publ*cvoidaccept(Visitorvisitor);} ConcreteElementpublicclassFloatElementimplementsVisitable{ privateFloatfe; publicFloatElement(Floatfe){ this.fe=fe;} 66Java设计模式(疯狂Java联盟版)publicFloatgetFe(){ returnthis.fe;} publicvoidaccept(Visitorvisitor){ visitor.*isitFloat(this);}} publicclassStringElementimplementsVisitable* privateStringse; publicString*lement(Stringse){ this.se=se;} publicStringgetS*(){ returnthi*.se;} publicvoidaccept(Visitorvisitor){ visitor.visitString(this);}} TestpublicclassTest{ publicstaticvoidmain(String[]args){ Visitorvisitor=newConcreteVisitor(); StringElementse=newStringElement(\"abc\");s*.accep*(visitor); Fl*atElementfe=newFloatElement(n*wFloat(1.5));fe.accept(visitor); S*stem.out.println(\"===========\");Listresult=newArrayList(); result.add(newStringEle*ent(\"abc\"));result.a*d(newStringElement(\"abc\"));result.add(*ewStringElement(\"abc\")); result.add(newFloatElement(newFloat(1.5)));result.add(newFloatElement(newFloat(1.5))); 67Java设计模式(疯狂Java联盟版)result.add(newFloatElement(newFloat(1.5)));visitor.visitCollection(result);}} resultabc1.5 ===========abcabcabc1.51.51.5 68 因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- 69lv.com 版权所有 湘ICP备2023021910号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务