android设计模式有哪些(android界面设计实例)

链接:

https://juejin.cn/post/6956555653229838350

前言

我曾经也有个决心,想把23种设计模式全部记住,但总是背了又忘,忘了又继续背,总是记不住。虽然网上有一大堆教学,分析,自己写一遍,比看十遍深刻多了。顺便学几个单词。话说回来,我们无时无刻都在根据设计模式写代码。
android设计模式有哪些(android界面设计实例)

1设计模式的七大原则

尽量用最简单的话描述

1、开闭原则(Open Closed Principle)

对类的扩展是开放,对修改关闭。

在程序需要扩展的时候,对于一个类,不要去修改原来的代码,而是通过继承的方式去扩展这个类。

目的:降低维护风险。

2、单一职责原则(Single Responsiblity Principle)

每个类应该且只有一个职责。

目的:提高可读性。

3、里式替换原则(Liskov Substitution Principle)

子类继承父类时,可以实现父类的抽象方法,不要 重写 父类的方法,子类增加自己特有的方法。

目的:防止继承带来的问题。

4、依赖倒转原则(Dependency Inversion Principle)

程序要依赖于抽象接口,不要依赖,于具体实现,针对接口编程。

目的:利于代码升级。

5、接口隔离原则(Interface Segregation Principle)

庞大的接口拆分成更小的和更具体的接口,一个接口只用于一个业务逻辑。

目的:使功能解耦,高内聚、低耦合。

6、迪米特原则(Principle of Least Knowledge)

一个对象应当对 其他 对象尽可能少的了解。

目的:自己做自己的事情。

7、合成复用原则(Composite Reuse Principle)

使用对象组合,而不是继承来达到复用的目的。

继承破坏了封装性,父类的任何改变,都可能导致子类出问题。

优先考虑 合成复用,A类和B类的合成使用,而不是B继承A的使用。

目的:少用继承 降低耦合。

223种设计模式

23种设计模式分为三类:

创建型模式、结构型模式、行为型模式。

顾名思义,创建型 就是怎么创建对象的。结构型就是对象与对象的关系,变成更大的结构。行为型 就是运行时复杂流程的 控制。

3创建型

1、单例模式(Singleton Pattern)

目的:主要就是一个类,频繁的创建,销毁。

优点:内存中只有一个实例,减少开销。

缺点:没有接口,不能继承,违背了单一职责原则。

实现:

1.懒汉式 静态方法,用到的时候再创建对象。

2.饿汉式 静态变量,直接new出对象。

3.双重锁 两个if判断,第一个if是为了防止不必要的线程同步,第二个if判断是为了避免 第二个线程 重复创建对象,volatile 为了防止指令重排。

4.kotlin关键字object也可以创建单例,原理和懒汉式类似在static块中创建 5.枚举的方式,枚举编译后,也是在static块中new出对象。

//双重锁publicclassSingleton{privatevolatilestaticSingletoninstance;privateSingleton(){};publicstaticSingletongetInstance(){if(instance==null){sychronized(Singleton.class){if(instance==null)instance=newSingleton();}}returninstatnce;}}

在android中有个隐藏抽象类。

publicabstractclassSingleton<T>{publicSingleton(){}privateTmInstance;protectedabstractTcreate();publicfinalTget(){synchronized(this){if(mInstance==null){mInstance=create();}returnmInstance;}}}privatestaticfinalSingleton<IActivityTaskManager>IActivityTaskManagerSingleton=newSingleton<IActivityTaskManager>(){@OverrideprotectedIActivityTaskManagercreate(){finalIBinderb=ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);returnIActivityTaskManager.Stub.asInterface(b);}};

这里用来获取了AMS对象,如果获取不到,就通过ServiceManager去获取。

这个Singleton是隐藏类,直接用不了,可以直接copy出来用。

2、工厂模式(Factory Pattern)

目的:解决接口选择问题。

优点:想要创建对象,只要知道名字就行,屏蔽了内部实现,只要关心接口。

缺点:增加一个产品的时候,需要增加一个实现类 和 一个工厂,比如Dagger2,新增一个注入的Bean,Dagger2就会为我们生成一个Factory类。空间增大了。

实现:

publicinterfaceClothes{voidgetClothes();}publicclassJacketimplementsClothes{@OverridepublicvoidgetClothes(){System.out.println(“夹克衫”);}}publicclassSweaterimplementsClothes{@OverridepublicvoidgetClothes(){System.out.println(“毛衣”);}}工厂假设他是衣柜publicclassWardrobeFactory{publicClothesgetShape(Stringshape){switch(shape){case”Jacket”:returnnewJacket();case”Sweater”:returnnewSweater();}returnnull;}}

衣柜假设是个工厂,衣柜里有衣服,抽象出衣服,衣服可以有夹克衫或者是毛衣。

在android中根据名字去拿对象,比如获取系统服务。

context.getSystemService(Service.ALARM_SERVICE)StringALARM_SERVICE=”alarm”

获取闹铃服务

3、抽象工厂模式(Abstract Factory Pattern)

目的:解决接口选择问题。

优点:当产品种类很多的时候 ,根据名字拿到的当前产品种类的对象。

缺点:扩展非常困难,增加一个同类新的产品,就需要增加一个新的工厂。

实现:

//裤子publicinterfaceTrousers{voidgetTrousers();}//牛仔裤publicclassJeansimplementsTrousers{@OverridepublicvoidgetTrousers(){System.out.println(“牛仔裤”);}}//短裤publicclassShortsimplementsTrousers{@OverridepublicvoidgetTrousers(){System.out.println(“短裤”);}}//衣服publicinterfaceClothes{voidgetClothes();}//毛衣publicclassSweaterimplementsClothes{@OverridepublicvoidgetClothes(){System.out.println(“毛衣”);}}//夹克衫publicclassJacketimplementsClothes{@OverridepublicvoidgetClothes(){System.out.println(“夹克衫”);}}//衣服和裤子都有了,抽象工厂//抽象工厂,这个工厂需要完成那衣服和裤子publicabstractclassAbsFactory{publicabstractTrousersgetTrousers(Stringtrousers);publicabstractClothesgetClothes(Stringclothes);}//生产衣服publicclassClothesFactoryextendsAbsFactory{@OverridepublicTrousersgetTrousers(Stringtrousers){returnnull;}@OverridepublicClothesgetClothes(Stringclothes){switch(clothes){case”Jacket”:returnnewJacket();case”Sweater”:returnnewSweater();}returnnull;}}//生产裤子publicclassTrousersFactoryextendsAbsFactory{@OverridepublicTrousersgetTrousers(Stringtrousers){switch(trousers){case”Shorts”:returnnewShorts();case”Jeans”:returnnewJeans();}returnnull;}@OverridepublicClothesgetClothes(Stringshape){returnnull;}}//衣橱类publicclassWardrobeFactory{publicstaticAbsFactorygetFactory(Stringchoice){switch(choice){case”Clothes”:returnnewClothesFactory();case”Trousers”:returnnewTrousersFactory();}returnnull;}}//使用//拿裤子AbsFactoryabsFactory=WardrobeFactory.getFactory(“Trousers”);//具体拿什么裤子Trousersshorts=absFactory.getTrousers(“Shorts”);//拿短裤shorts.getTrousers();

代码比较多,还是比较清晰的,把工厂抽象了一下。

在android中,抽象工厂比较少,可以把整个Service看做一个大抽象工厂,通过名字去拿服务,拿到服务对象,再调用对象里的抽象方法。

4、原型模式(Prototype Pattern)

目的:快速,高效的创建对象。

优点:提高性能,没有构造函数的限制。

缺点:配合克隆方法进行,需要考虑深拷贝和浅拷贝的问题。

实现:

publicclassSheepimplementsCloneable{Stringname;publicSheep(Stringname){this.name=name;}publicObjectclone(){Objectobj=null;try{obj=super.clone();}catch(CloneNotSupportedExceptione){e.printStackTrace();}returnobj;}}

完成Cloneable方法,增加一个clone方法,Object也有一个克隆方法,这是调用了Native方法,底层去克隆了一个对象。

在android中:

publicclassIntentimplementsParcelable,Cloneable{@OverridepublicObjectclone(){returnnewIntent(this);}}//okhttp中也用到了@OverridepublicRealCallclone(){returnRealCall.newRealCall(client,originalRequest,forWebSocket);}

说到底也就是复制一个新对象。

5、建造者模式(Builder Pattern)

目的:配置一个复杂对象。

优点:独立,容易扩展。

缺点:如果对象复杂,会有很多建造者类。

实现:

publicclassDialog{Stringtitle;booleanmCancelable=false;Dialog(Stringtitle,booleanmCanclable){this.title=title;this.mCancelable=mCanclable;}publicvoidshow(){System.out.print(“show”);}staticclassBuilder{Stringtitle;booleanmCancelable=false;publicBuildersetCancelable(booleanflag){mCancelable=flag;returnthis;}publicBuildersetTitle(Stringtitle){this.title=title;returnthis;}publicDialogbuild(){returnnewDialog(this.title,this.mCancelable);}}}

这个建造者不拘泥于形式,建造者模式用于创建一个复杂对象。在android中,Dialog就用到了建造者模式,第三方库的okhttp、Retrofit。

4结构型

6、代理模式(Proxy Pattern)

目的:增强他的职责,比如访问远程的服务器,如果直接访问可能会带来一些麻烦,通过一个代理去帮我们访问。

优点:职责清晰,易扩展。

缺点:增加了代理可能会导致速度慢,代理类会比较复杂。

实现:

//访问数据库接口publicinterfaceDataBase{voidselect();}//正真做查询操作publicclassRealImageimplementsDataBase{@Overridepublicvoidselect(){System.out.println(“查询”);}}//代理类publicclassProxyDBimplementsDataBase{RealImagerealImage;publicProxyDB(){if(realImage==null){realImage=newRealImage();}}@Overridepublicvoidselect(){realImage.select();}}//使用DataBaseproxyDb=newProxyDB();proxyDb.select();

这里用了ProxyDB 这个代理类,去访问数据,并没有直接去访问数据库。在android中,当我们编写好AIDL文件后,编译器会自动给我们增加一些代码。

publicinterfaceIRemoteServiceextendsandroid.os.IInterface{publicstaticabstractclassStubextendsandroid.os.Binderimplements…{publicstaticcom.learnaidl.IRemoteServiceasInterface(..){returnnew..Proxy(obj);}privatestaticclassProxyimplementscom.learnaidl.IRemoteService{…}}}//使用IRemoteService.Stub()

通过IRemoteService的Stub类拿对象,这个对象是通过一个代理类创建出来的。

换个角度看,代理模式也就是 实现了一个接口,并完成了一个方法,这个方法可以去做任何事情。

7、外观模式(Facade Pattern)

目的:降低系统复杂度。

优点:提高灵活性,安全性。

缺点:违反了开闭原则、迪米特原则,改东西相对麻烦。

实现:

//接口有个打开的动作publicinterfaceAction{voidopen();}//灯实现了开灯publicclassLampimplementsAction{@Overridepublicvoidopen(){System.out.println(“开灯”);}}//电视实现了打开电视publicclassTVimplementsAction{@Overridepublicvoidopen(){System.out.println(“开电视”);}}//遥控器可以控制灯和电视publicclassRemoteControl{Actionlamp;Actiontv;publicRemoteControl(){lamp=newLamp();tv=newTV();}publicvoidopenLamp(){lamp.open();}publicvoidopenTv(){tv.open();}}

遥控器既可以开灯,又可以开电视。可见这个“遥控器”职责并不单一。也不用局限于接口,如果是功能聚合到一个类中,依然可以叫外观模式。想象成 前台、接待员。

在android中,Context就用了外观模式,Context可以打开Activity,可打开Service,广播等等。

8、装饰器模式(Decorator Pattern)

目的:解决扩展子类膨胀的问题,比如摊煎饼,可以摊煎饼前,煎个鸡蛋,摊煎饼后,撒点酱。

优点:灵活扩展 缺点:过多的装饰,会很复杂 实现。

//一个煎饼接口publicinterfacePancake{voidpancake();}//牛肉煎饼publicclassBeefPancakeimplementsPancake{@Overridepublicvoidpancake(){System.out.println(“牛肉煎饼”);}}//工作人员publicclassWorker{Pancakepancake;publicWorker(){pancake=newBeefPancake();}publicvoidmakePancake(){System.out.println(“煎鸡蛋”);pancake.pancake();System.out.println(“撒酱”);}}//使用Workerworker=newWorker();worker.makePancake();

说白了,装饰模式,装饰东西,实际作用的前后装饰一些其他内容。

在android中,Context,ContextImpl也就是个装饰模式,我们肯定会在startActivity()前后做点业务操作。

9、享元模式(Flyweight Pattern)

目的:为了解决大量创建相同对象,可能造成OOM。

优点:减少重复创建对象,降低内存。

缺点:提高了系统的复杂度,如果固定了一些对象,当被改变时候,会造成混乱。

实现:

//假设有个请求的类publicclassRequest{}//通过一个地方去拿请求publicclassHttpFactory{publicstaticfinalHashMap<String,Request>requestMap=newHashMap<>();publicRequestgetRequestList(Stringname){Requestrequest=(Request)requestMap.get(name);if(request==null){request=newRequest();requestMap.put(name,request);}returnrequest;}}//使用HttpFactoryfactory=newHttpFactory();Requestrequest1=factory.getRequestList(“baidu”);//假设过了一会Requestrequest2=factory.getRequestList(“baidu”);

相当于是缓存了一块地方,把对象放进去,需要对象的时候就从这里面取,如果相同需求,则会返回已有的对象。

在android中,获取Message,可以通过Message.obtain()去获取Message。在JVM中缓存了很多字符串。可以说我们任何时候都在使用享元模式。

10、组合模式(Composite Pattern)

目的:用来描述整体和部分的关系,比如在树中,一个结点可以是根节点,也可以是叶子节点。

优点:调用简单,结点可以自由增加。

缺点:在组合模式中,依赖的都是实现类,而不是接口,违反了依赖倒置原则 。

实现:

//二叉树publicclassListNode{intdata;ListNodeleft;ListNoderight;}

二叉树的结点,既可以是根节点,又可以是叶子节点。在android中,View和ViewGroup的关系,ViewGroup既可以是一个View,又可以包含View。

11、适配器模式(Adapter Pattern)

目的:解决两个不兼容接口的桥梁,兼容转换。

优点:让两个没有关联的类一起运行,提高复用。

缺点:使用过多,会让系统变的凌乱。

实现:

//定义适配器类publicclassAdapter{publicvoidgetView(inti){System.out.println(“给出View” i);}}//ListView继承了AdapterpublicclassListViewextendsAdapter{publicvoidshow(){System.out.print(“循环显示View”);for(inti=0;i<3;i ){getView(i);}}}//GridView继承了AdapterpublicclassGridViewextendsAdapter{publicvoidshow(){…getView(i);}}

适配器模式可以用继承实现,这里没有更高的抽象,当然也可以把Adapter的内容抽象出去,仅仅演示,ListView、GridView适配了Adapter类。

在android中,ListView、RecyclerView都是用了适配器模式,ListView适配了Adapter,ListView只管ItemView,不管具体怎么展示,Adapter只管展示。就像读卡器,读卡器作为 内存和电脑 之间的 适配器。

12、桥接模式(Bridge Pattern)

目的:将两个能够独立变化的类分开,不用继承,继承会造成类的爆炸增长。

优点:抽象分离,易扩展,细节透明。

缺点:会增加系统的设计难度。

实现:

//颜色接口publicinterfaceColor{voiddraw(Stringbox);}//红色完成方法红色的somethingpublicclassRedColorimplementsColor{@Overridepublicvoiddraw(Stringsth){System.out.println(“red” sth);}}//抽象类盒子publicabstractclassBox{Colorcolor;publicBox(Colorcolor){this.color=color;}abstractvoidgetBox();}//实现类红色盒子publicclassRedBoxextendsBox{publicRedBox(Colorcolor){super(color);}@OverridevoidgetBox(){this.color.draw(“box”);}}//使用RedColorredColor=newRedColor();Boxbox=newRedBox(redColor);box.getBox();

如果类存在两个维度的变化,比如颜色可能有红色、绿色,包可能有手提包,钱包。对于这两个维度的变化,适合用桥接。更直观的说,比如一个USB线左边可以插不同的手机,右边可以插不同的电源。

在android中,整个View的视图,View、Button、ViewGroup等等都是在View这个维度上的变化,都有onDraw()方法来实现不同的视图。另一个维度就是把View绘制到屏幕上。私以为,这RexBox相当于一个View,RedColor相当于绘制到屏幕上。

5行为型

13、模板模式(Template Pattern)

目的:固定了一些方法,只要照着做就行,比如把大象放进冰箱,打开冰箱,放进冰箱,关闭冰箱。

优点:行为由父类控制,便于维护。

缺点:导致类增多,系统变大。

实现:

publicabstractclassBaseActivity{abstractvoidonCreate();abstractvoidonDestory();}publicclassHomeActivityextendsBaseActivity{@OverridevoidonCreate(){}@OverridevoidonDestory(){}}

它的主旨就是抽象出公共的方法,子类照着重写就行,行为由父类控制。

这个。。。作为android开发者天天都在用。。。

14、策略模式(Strategy Pattern)

目的:解决很多if else的情况。

优点:可以避免多重判断条件,扩展性好。

缺点:类会增多。

实现:

//假如RecyclerView这样写publicclassRecyclerView{privateLayoutlayout;publicvoidsetLayout(Layoutlayout){this.layout=layout;if(layout==”横着”){}elseif(layout==”竖着”){}elseif(layout==”格子”){}else{}this.layout.doLayout();}}//这样写if就很多了//排列的方式publicinterfaceLayout{voiddoLayout();}//竖着排列publicclassLinearLayoutimplementsLayout{@OverridepublicvoiddoLayout(){System.out.println(“LinearLayout”);}}//网格排列publicclassGridLayoutimplementsLayout{@OverridepublicvoiddoLayout(){System.out.println(“GridLayout”);}}publicclassRecyclerView{privateLayoutlayout;publicvoidsetLayout(Layoutlayout){this.layout=layout;this.layout.doLayout();}}

这里直接举了android中RecyclerView的例子,我们给RecyclerView选择布局方式的时候,就是选择一个策略。

15、中介者模式(Mediator Pattern)

目的:解决对象与对象之间的耦合关系。

优点:降低复杂度,各个类之间解耦。

缺点:中介者会过于庞大不好维护。

实现:

//聊天室publicclassChatRoom{publicstaticvoidshowMessage(Useruser,Stringmsg){System.out.println(user.name “:” msg);}}//用户publicclassUser{Stringname;publicUser(Stringname){this.name=name;}publicvoidsendMessage(Stringmsg){ChatRoom.showMessage(this,msg);}}//使用Userh1=newUser(“h1”);Userh2=newUser(“h2”);h1.sendMessage(“hello”);h2.sendMessage(“youtoo~”);

这个聊天室就相当于个中介者,给两个人传递消息。如果聊天室新增功能,会导致聊天室的代码越来越多,不好维护。

在android中,无时无刻都在使用中介者,MVP 的 P ,MVC的 C ,MVVM 的 VM,你和我。???

16、观察者模式(Observer Pattern)

目的:一个对象改变通知其他对象,保证协作。

优点:观察者和被观察者是抽象耦合的,也就是说通过抽象方法,给具体的类通知。

缺点:如果观察者有很多,被观察者发消息,会慢,如果不小心观察者和被观察者有依赖,会循环引用。

实现:

//抽象类做作业publicabstractclassDoWork{protectedTeacherteacher;abstractvoiddoHomeWork(inti);}//老师publicclassTeacher{privateList<Student>students=newArrayList<>();privateintindex;publicvoidattach(Studentstudent){this.students.add(student);}publicvoiddispatchHomeWork(intindex){this.index=index;notifyAllStudent();}publicvoidnotifyAllStudent(){for(Studentstu:students){stu.doHomeWork(index);}}}//学生类publicclassStudentextendsDoWork{publicStudent(Teacherteacher){this.teacher=teacher;this.teacher.attach(this);}@OverridevoiddoHomeWork(inti){System.out.println(this “:做作业” i);}}//使用Teacherteacher=newTeacher();newStudent(teacher);newStudent(teacher);newStudent(teacher);teacher.dispatchHomeWork(1);teacher.dispatchHomeWork(3);

这个很好实,关键代码就是通过一个ArrayList保存观察着。

其实在java中,jdk已经实现好的观察者模式。点开源码就会发现他保存的是个向量。

publicclassObservable{privatebooleanchanged=false;privateVector<Observer>obs;}17、状态模式(State Pattern)

目的:对象依赖一个状态,对象可以根据状态改变自己的行为。

优点:状态转换与逻辑合在一起,而不是通过if语句隔开。

缺点:会使结构比较复杂,也会增加类的个数。

实现:

//状态接口publicinterfaceState{voiddoAction(MediaPlayeractivity);}//开始状态publicclassOnStartimplementsState{@OverridepublicvoiddoAction(MediaPlayeractivity){System.out.println(activity “:OnStart”);}}//结束状态publicclassOnStopimplementsState{@OverridepublicvoiddoAction(MediaPlayeractivity){System.out.println(activity “:OnStop”);}}//播放器publicclassMediaPlayer{Statestate;publicvoidsetState(Statestate){this.state=state;}publicStategetState(){returnstate;}}//使用MediaPlayeractivity=newMediaPlayer();OnStartonStart=newOnStart();onStart.doAction(activity);OnStoponStop=newOnStop();onStop.doAction(activity);

定义了两个状态,开始和结束,让播放器 依赖这两个状态进行操作。

在android中,就比如播放器,依赖自身的状态,进行播放暂停操作。再比如Fragment,Fragment走自己的onCreate等方法,也是依赖Activity的生命周期状态进行操作。

18、责任链模式(Chain of Responsibility Pattern)

优点:解耦,简化操作。

缺点:性能会有一点影响,调试不太方便。

实现:

//责任链接口publicinterfaceInterceptor{Stringchain(StringinData);}//缓存publicclassCacheInterceptorimplementsInterceptor{@OverridepublicStringchain(StringinData){returninData =”加了缓存”;}}//呼叫服务器publicclassCallServerInterceptorimplementsInterceptor{@OverridepublicStringchain(StringinData){returninData =”呼叫了服务器”;}}//把责任集合起来publicclassRealInterceptor{List<Interceptor>list=newArrayList<>();publicRealInterceptor(){list.add(newCacheInterceptor());list.add(newCallServerInterceptor());}publicStringrequest(Stringst){Stringresult=””;for(inti=0;i<list.size();i ){result =list.get(i).chain(st);}returnresult;}}//使用RealInterceptorrealInterceptor=newRealInterceptor();Stringresult=realInterceptor.request(“请求->”);System.out.println(result);

责任链就是想链条一样,也可以在中间增加或减少,像”击鼓传花”,一个个传递。

在android中,事件分发机制,父View接到事件,传递给子View。在第三方库okhttp中一个网络请求用的也是拦截器模式。

19、备忘录模式(Memento Pattern)

目的:不破坏封装的前提下,捕获一个对象的内部状态,并保存,之后能根据状态恢复到原来的样子。

优点:提供了一种可以恢复的机制,封装了信息,用户不需要过多关心细节。

缺点:消耗资源,如果保存内容过多过大,会占用很多资源。

实现:

//Layer表示一层publicclassLayer{privateStringstate;publicLayer(Stringstate){this.state=state;}publicStringgetState(){returnstate;}publicvoidsetState(Stringstate){this.state=state;}}//管理层publicclassManager{privateLayermLayer;publicLayersave(Stringstate){returnnewLayer(state);}publicvoidrestore(Layerlayer){mLayer=layer;}publicLayergetmLayer(){returnmLayer;}}//正真用这个层publicclassPhotoShop{privateList<Layer>layerList=newArrayList<>();publicvoidctrl_S(LayermLayer){layerList.add(mLayer);}publicLayerctrl_Z(intindex){returnlayerList.get(index);}}//使用PhotoShopps=newPhotoShop();Managermanager=newManager();ps.ctrl_S(manager.save(“第一层”));ps.ctrl_S(manager.save(“第二层”));manager.restore(ps.ctrl_Z(1));System.out.println(“当前是:” manager.getmLayer().getState());ps.ctrl_S(manager.save(“第三层”));ps.ctrl_S(manager.save(“第四层”));manager.restore(ps.ctrl_Z(3));System.out.println(“当前是:” manager.getmLayer().getState());

就像Ps一样,Ctrl S 保存一层,Ctrl Z回退一层。就像玩游戏的存档一样。

在android中,Activity的onSaveInstanceState保存数据在onCreate里 恢复数据。

20、迭代器模式(Iterator Pattern)

目的:遍历一个对象。

优点:访问一个聚合数据,聚合数据不会暴露内部内容。

缺点:会增加类的个数,增加系统复杂性。

实现:

//迭代接口publicinterfaceIterator{booleanhasNext();Objectnext();}//容器接口publicinterfaceContainer{IteratorgetIterator();}//容器publicclassNameContainerimplementsContainer{publicString[]names={“name1″,”name2″,”name3″,”name4”};@OverridepublicIteratorgetIterator(){returnnewNameIterator();}classNameIteratorimplementsIterator{intindex;@OverridepublicbooleanhasNext(){if(index<names.length){returntrue;}returnfalse;}@OverridepublicObjectnext(){if(this.hasNext()){returnnames[index ];}returnnull;}}}//使用NameContainernameContainer=newNameContainer();Iteratorit=nameContainer.getIterator();while(it.hasNext()){Stringname=(String)it.next();System.out.println(name);}

Iterator接口,必须实现下一个 对象 和 是否有下一个对象。Container接口 需要返回一个实现Iterator接口的类。

在java中HashMap的内部类KeySet有Iterator,android中访问数据库有Cursor,都是是用了迭代器模式

21、解释器模式(Interpreter Pattern)

目的:对于一些固定问法结构如xml,构建一个类解释它。

优点:扩展性好、灵活、增加了新的表达方式。

缺点:使用场景少,难维护,通常要用到递归。

实现:

//先看使用SelectInterpreterselectInterpreter=newSelectInterpreter();selectInterpreter.interpreter(“查t_name”);//解释器接口publicinterfaceInterpreter{Stringinterpreter(Stringsql);}//查询的解释器publicclassSelectInterpreterimplementsInterpreter{@OverridepublicStringinterpreter(Stringsql){//select*fromt_user//selectt_userif(sql.indexOf(“查”)==0){intstart=sql.indexOf(“查”) 1;intend=sql.length();StringtableName=sql.substring(start,end);System.out.println(“查询表:” tableName);}else{System.out.println(“sqlerror”);}returnnull;}}

sql是一种描述语言,通常sql查询一个表需要select * from t_user,这是数据库定义的语法。

现在由我来 解释,想要查询我的数据库,直接查t_name,就可以了。虽然有点扯,但应该最好理解了。

在android中,通常会定义xml布局,然后setContentView(xml),把xml放进去,这个里面就用了解释器模式,通过XmlResourceParser等一些方法,把xml解释成对象。

22、命令模式(Command Pattern)

目的:也是用来解耦的。通常请求者和实现者是一种耦合关系,但一些场合对行为记录、撤销、重做,这种请求和处理就不太适合在一起 优点:解耦,易扩展 缺点:命令类可能会变的很多。

实现:

//命令接口publicinterfaceOrder{voidexecute();}//买的命令publicclassBuyStockimplementsOrder{Stockstock;publicBuyStock(Stockstock){this.stock=stock;}@Overridepublicvoidexecute(){this.stock.buy();}}//卖的命令publicclassSellStockimplementsOrder{Stockstock;publicSellStock(Stockstock){this.stock=stock;}@Overridepublicvoidexecute(){this.stock.sell();}}//业务类股票publicclassStock{publicvoidbuy(){System.out.println(“buy”);}publicvoidsell(){System.out.println(“sell”);}}//经理人publicclassManager{privateList<Order>list=newArrayList<>();publicvoidtakeOrder(Orderorder){this.list.add(order);}publicvoidplaceOrder(){for(Orderorder:list){order.execute();}list.clear();}}//使用//经理人Managermanager=newManager();//一个股票Stockstock=newStock();//命令1买股票Orderorder1=newBuyStock(stock);//命令2卖股票Orderorder2=newSellStock(stock);manager.takeOrder(order1);manager.placeOrder();manager.takeOrder(order2);manager.placeOrder();

4个类,一个买股票的类,一个卖股票的类,一个经理人,一个股票。买和卖相当于一条命令,也可以增加其他的命令。一句话,定义一条买股票的命令,把命令交给经理人,经理人去执行。在android中,PackageManagerService用到了命令模式,实现对apk的解析、管理等操作。

私以为这个命令模式比较宽泛,将一个请求封装成一个对象,对这个请求有记录或者撤销等操作。比如线程池使用、okhttp一个请求用的Call,都可以视作命令。

23、访问者模式(Visitor Pattern)

目的:解决稳定的数据结构和易变的操作耦合问题。

优点:符合单一职责,易扩展。

缺点:违反了迪米特原则、依赖倒置原则,依赖了具体实现类,不是依赖抽象。

实现:

//行为模式中最复杂的一个模式,先看代码//抽象类动作publicabstractclassAction{abstractvoidaccept(Visitorvisitor);}//相机系统publicclassCameraSystemextendsAction{@Overridevoidaccept(Visitorvisitor){visitor.visitor(this);}}//图片系统publicclassImageSystemextendsAction{@Overridevoidaccept(Visitorvisitor){visitor.visitor(this);}publicintgetSize(){return10;}}//访问者接口publicinterfaceVisitor{voidvisitor(ImageSystemimageSystem);voidvisitor(CameraSystemcameraSystem);}//app1实现访问者接口publicclassApp1implementsVisitor{@Overridepublicvoidvisitor(ImageSystemimageSystem){System.out.print(“访问图片”);System.out.print(“一共” imageSystem.getSize());}@Overridepublicvoidvisitor(CameraSystemcameraSystem){System.out.print(“访问相机”);}}//使用App1app1=newApp1();ImageSystemimageSystem=newImageSystem();imageSystem.accept(app1);

看上去代码不是非常复杂,我写了一个比较好理解的代码,访问者肯定是访问内容。

一个动作的抽象类,图片系统和相机系统完成了这个动作。App1 实现了访问者接口,表示App1可以 访问 图片系统和相机系统。

再换个例子,比如棉花和纸,在做衣服的工厂可以做成毛衣和标签牌子,在造钱的工厂,可以做成纸币和包装袋。

访问者的目的是:稳定的数据结构 和 异变的操作 ,耦合问题,我觉着应该不用在解释了。

总结

23种设计模式,分为创建型、结构型、行为型,都是围绕七大设计原则,当然有些设计模式牺牲了一些原则,换取更好的效果。

抛开设计模式来看,所有的代码,无非用到了,抽象类、接口、实现类,再加上接口和实现类的组合、实现类与实现类的组合而写成的代码。

设计模式是代码设计经验的总结,我们根据这些总结,开发出易于他人理解、可靠可重用的代码。

参考:

https://www.runoob.com/design-pattern/design-pattern-tutorial.html

推荐阅读:

RecyclerView 中的秘密探索 | 滚动Google 还发布了这个库? 告别shape、各种 drawable…一个困惑很久的问题,Android中有子窗口吗?

如果你想要跟大家分享你的文章,欢迎投稿~

┏(^0^)┛明天见!

发表评论

登录后才能评论