Java23种设计模式
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实例。
类图
例子
*roduct
publicinterfaceWork{
voiddoWork();
}
ConcreteProduct
publicclassStudentWorkimplementsWork{
publicvoiddoWork(){
System.out.println("学生*作业!");
}
}
publicclassTeacherWorkimplementsWork{
publicvoiddoWork(){
System.out.println("老师审批作业!");
}
}
Creator
publicinterfaceIWorkFactory{
Workget*ork();
}
Concre*eCreator
pu*licclassStudentWorkFactoryimplementsIWorkFactory{
publicWorkgetWork(){
*eturnnewStudentWork();
}
}
publicclassTeacherWorkFactoryimplementsIWorkFactory{
publicWorkgetWork(){
returnnewTeacherWork();
}
}
Test
publicclassTest{
publicstaticvoidm*in(Strin*[]args){
IWorkFactorystudentWorkFactory=newStudentWorkFactory();
studentWorkFactory.getWork().d*Work();
IWorkFactoryteacherWorkFactory*newTeacherWorkFactory();
teacherWorkFactory.g*tWork().*oWork();
}
}
result
学生做作业!
老师审批作业!
1.1.2抽象工厂
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
适用性
1.一个系统要独立于它的*品的创建、组合和表示时。
2.一个系统要由多个产品系列中的一个来配置时。
3.当你要强调一系列相关的产品对象的设计以便进行联合使用时*
4*当你提供一个产品类库,而只想显示它们*接口而不是实现时。
参与者
1.Ab*tractFactory
声明一个创建抽象产品对象的操作接口。
2.ConcreteFactory
实现创建具体产品对象的操作。
*.AbstractProduct
为一类产品对象声明一个接口。
4.ConcreteProdu*t
定义一个将被相应的具体工厂创建的产品*象。
实现*bstractProduct接口。
5.Client
仅使用由AbstractFactory和AbstractProduc*类声明的接口
类图
例子
*bstractFactory
publicinterfaceIAn*malFactory{
ICatcreateCat();
IDogcre*teDog();
}
ConcreteFactory
p*blicclassBlackAnimalFactoryimplem*ntsIAnimalFactory{
publicICatcreateCat(){
retur*newBlackCat();
}
publicIDogcreateDog(){
returnnewBlackDog();
}
}
publicclassWhiteAnimalFac*oryimp*ementsIAnimalFactory{
publicICatcreateCat(){
returnnewWhiteCat();
}
publicIDogcre*teDog(){
returnnewWhiteDog();
}
}
Abstrac*Product
publicinterfaceICat{
voideat();
}
publicinterfaceIDog{
voideat();
}
Concrete*roduct
publicclassBlack*atimplementsICat{
publicvoideat(){
System.out.println("Thebl*ckcatiseating!");
}
}
publicclassWhiteCatimplements*Cat{
publicvoideat(){
Sy*tem.out.prin*ln("Thew*itecatiseating!*);
}
}
publicclassBlackDogimplementsIDog{
publicvoideat(){
System.out.println("Theblackdogiseating");
}
}
publicclassWhiteDogimplementsIDog{
publicvoideat(){
System.out.println("Thewhitedogiseat*ng!");
}
}
Client
publicstaticvoidmain(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*lt
Thebla*kcatiseating!
Th*blackdogiseatin*!
Thewhitecatiseating!
Thewhitedogis*ating!
1.1.3建造者模式
将一个复杂对象的构*与它的表示分离,使*同样的构建过程可以创建不同的表示。
适用性
1.当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
*.当构造过程必须允*被构造的对象有不同*表示时。
参与者
1.Builder
为创建一个Product对象的各个部件指定抽象接口。
2.ConcreteBuilder
实现Buil*er的接口以构造和装配该产品的各个部件。
定义并明确它所创建的表示*
提供一个检索产品的接口。
3.Director
构造一个使用Builder接口的对象。
4.Product
表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。
包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
类图
例子
Buil*er
publicinterfacePersonBuilder{
voidbuildHead();
v*idbuildBody();
voidbuildFoot()*
PersonbuildPerson();
}
ConcreteBuilder
publicclassManBuilderimplementsPersonB*ilder{
Personperson;
publicManBuilder(){
person=ne*Man();
}
publ*cvoidbuild*ody(){
perso*.setBody("建造男人的身体");
}
publicvoidbuildFoot(){
person.setFo*t("建造男人的脚");
}
publicvoidbuildHead(){
pers*n.setHead("建造*人的头");
}
*ublicPersonbuildPerson(){
retur*person;
}
}
Dir*ctor
publicclassPersonDirec*or{
publicPersonconstructPerson(PersonBuilderpb){
pb.buildHead();
pb.buildBody();
pb.buildFoot();
returnpb.buildPerson();
}
}
Product
publicclassPerson{
privateStringhead;
privateStringbody;
privateStringfoot;
publicStringgetH*ad(){
returnhead;
}
publicvoidsetHead(Stringhea*){
this.head=head;
}
publicStringgetBody(){
returnbody;
}
publicvoidsetBody(Stringbody){
this.b*dy=body;
}
publicStringgetFoot(){
returnfoot;
}
publicvoidsetFoot(Stringfoot){
t*is.foot=foot;
}
}
publicclassManextendsPerson{
}
Test
publ*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.当类只能有一个*例而且客户可以从一个众所周知的访问点访问它时。
2.当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
参与者
Singleton
定义一个Instance操作,允许客户访问它的唯一实例。Instance是一个类操作。
可能负*创建它自己的唯一实例。
类图
例子
Singleton
publicclassSingleton{
privatestaticSingletonsing;
privateSingleton(){
}
publicst*ticSingletonget*nstance(){
if(sing==null){
sing=newSingleto*();
}
returnsing;
}
}
Test
publicclassTest{
publicstaticvoid*ain(*tring[]args){
Singletonsing=Singleton.getInstance();
Singletonsi*g2=Singleton.getI*stance();
System.out.println(sing);
System.out.pr*ntln(sing2);
}
}
result
singleton.Singleton@1c78e57
singleton.Singleton@1c78e57
1.1.5原型模式
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
适用性
1.当一个系统应该独立于它的产品创*、构成和表示时。
2.当要实例化的类是在运行时刻指定时,例如,通过动态装载。
3.为了避免创建一个与产品类层次平行的工厂*层次时。
4.当一个类的实例只能有几个不同状态组合中的一种时。
建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
参与者
1.Prototype
声明一个克隆自身的接口。
2.ConcretePrototype
实现一个克隆自身的操作。
3.Client
让一个原型克*自身从而创建一个新的对象。
类图
例子
Prototype
publicclassPrototypeimplementsCloneable{
privateStringname;
publicvoidsetName(Stringname){
this.name=name;
}
publicStringgetName(){
returnthis.name;
}
publicObjectclone(){
try{
returnsuper.clone();
}catch(Exceptione){
e.printStackTrace();
returnnull;
}
}
}
ConcretePrototype
publ*cclassConcretePrototypeextend*Prototype{
publicConcretePrototype(Stringname){
setName(name);
}
}
Client
publicclas*Test{
publicstaticvoidmain(String[]args){
Prototypepro=newConcretePrototy*e("prototype");
Prototypepro2=(Prototype)pro.clone();
*ystem.out.println(pro.getName()*;
System.out.println(pro2.getName());
}
}
result
prototype
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接口进行适配
类图
例子
Target
publicinterfaceTarget{
voidadapteeMethod();
voidadapterMethod();
}
Adaptee
publicclassAdaptee{
publicvoidadapteeMethod(){
Syste*.out.p*intln("Adapteemethod!");
}
}
Adapt*r
publicclas*Adapterimplement*Target{
privateAdap*eeadaptee;
publicAdapter(Adapteeadaptee){
this.adapte*=adaptee;
}
publicvoidadapteeMethod(){
adaptee.adapteeMethod();
}
publicvoidadapterMethod(){
*ystem.out.println("Adaptermethod!");
}
}
Client
publiccla*sTest{
publicstati*voidmain(String[]args){
Targettarget=newAdapter(newAdaptee());
tar*et.adapteeMethod();
target.adapterM*thod();
}
}
result
Adapteemethod!
Adaptermethod!
1.2.2桥接模式
将抽象部分与它*实现部分分离,使它们都可以独立地变化。
适用性
1.你不希望在抽*和它的实现部分之间有一个固定的绑定关系。
例如这种情况可能是因为,在程序运行时刻实现部分应可以*选择或者切换。
2.类的抽象以及它的实现都应该可以通*生成子类的方法加以扩充。
这时Bridge模式使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
3.对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
4.正如在意图一节的第一个类图中所示的那样,有许多类要生成。
这*一种类层次结构说明你必须将一个对象分解成两个部分。
5.*想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知*这一点。
参与者
1.Abstraction
定义抽象类的接口。
维护一个指向Implementor类型对象的指针。
2.RefinedAbstraction
扩充由Abstraction定义的接口。
3.Implementor
定义实现类的接口,该接口不一定要与Ab*traction的接口完全一致。
事实上这两个接口可以完全不同。
*般来讲,Implementor接口仅提供基本操作,而Abstraction则定义了基于这些基本操作的较高层次的操作。
4.ConcreteImplementor
*现Implementor接口并定义它的具体实现。
类图
例子
Abstr*ction
publicabstractclassPerson{
privateClothingclothing;
pr*vateStringtype;
publicClothinggetClothing(){
returnclothing;
}
publi*voidsetClothing(){
this.clothing=*lothingFactory.getClothing();
}
publicvoidsetType(Stringtype){
t*is.type=type;
}
publicStringgetType(){
returnthis.ty*e;
}
publicabstractvoiddress();
}
RefinedAbstraction
publicclassManextends*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{
publicvoidpersonDressCloth(Personperson){
System.out.println(person.getType()+"穿马甲");
}
}
publiccl*ssTrouserextendsClothing{
publicvoidpersonDressCloth(Personperson){
System.ou*.println(*erson.getType()+"穿裤子");
}
}
Test
publicclassTe*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组合模式
将对象组合成树形结构以表示"部分-整体"的层次结构。"Composite使得用户对单个对象和组合对*的使用具有一致性。"
适用性
1.你想表示对象的部分-整*层次结构。
2.你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
参与者
1.Component
为组合中的对象声明接口。
在适当的情况下,实现所有类共有接口的缺省行为。
声明一个接口用于访问和管理Component的子组件。
(可选)在递归结构中定义一个接口,用于访问一个父部件,并在合*的情况下实现它。
2.Leaf
在组合中表示叶节点对象,叶节点没有子节点。
在组合中定义节点对象的行为。
3.Compos*te
定义有子部件的*些部件的行为。
存储子部件。
在Component接口中实现与子部件有*的操作。
4.Client
通过Component接*操纵组合部件的对象。
类图
例子
Component
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;
}
}
Leaf
publicclassProgrammerextendsEmployer{
publicProgrammer(Stringname){
setNam*(name);
employers=null;//程序员,表示没有下属了
}
publicv*idadd(Employeremployer){
}
publicvoiddelete(Employeremployer){
}
}
publicclassPro*ectAssistantextendsEmployer{
publicProjectAss*stant(Stringname){
setName(name);
employers=*ull;//项目助理,表示没有下属了
}
publicvoidadd(Employeremployer){
}
publicvoiddelet*(Employeremployer){
}
}
Composite
publicclassProject*anagerextendsE*ployer{
publicProjectManager(Stringname){
setName(name);
employers=newA*rayList();
}
publicvoidadd(Employeremployer){
employers.add(employer);
}
publicvoiddelete(Emplo*eremployer){
employers.remove(employer);
}
}
Clie*t
publ*cclassTest{
publicst*ticvoidmain(String[]args){
Employerpm=newProjectManager("项目经理");
Emplo*erpa=newProjectAssistant("项目助理");
Employerprogra*mer1=newProgrammer("程序员一");
Employerprogrammer2=newProgrammer("程序员二");
pm.add(pa);//为项目经理添加项目助理
pm.add(programmer2);//*项目经理*加程序员
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
向组件添加职责。
类图
例子
Component
publicinterfacePerson{
voideat();
}
ConcreteComponent
*ublicclassM*nimplementsPerson{
publicvoideat(){
System.out.println("男人在吃");
*
}
Decorator
publicabstrac*classDecoratorimplementsPerso*{
protectedPersonperson*
publicvoidsetPerson(Personperson){
this.person=person;
}
publicvoideat(){
person.eat();
}
}
ConcreteDec*rator
publi*classManDecoratorAextendsDecorator{
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类");
}
}
Test
publicclassTest{
publicst*ticvoidmain(Strin*[]args){
Manman=newMan();
ManDecoratorAmd1=newManDecoratorA();
ManDecoratorBmd2=n*wManDecoratorB();
md1.setPerson(man);
md2.setPerson(md1);
md2.eat();
}
}
result
男人在吃
再吃一顿饭
ManDecoratorA类
===============
ManDecoratorB类