This article describes the adapter mode (Adapter pattern), the adapter mode used in the development of the frequency is also very high, such as the ListView and Recyclerview Adapter, etc. are used in the adapter mode. In our real life there are a lot of examples like adapters, such as Hong Kong's sockets and the mainland's sockets are two formats, in order to successfully adapt, usually in the middle with a power adapter, shaped like:
This makes it possible to successfully connect existing systems and target systems that were not previously compliant with the adapter.
In the end, the adapter pattern is to fuse the two classes that were originally incompatible, which is a bit like an adhesive that transforms different things through a transformation so that they can work together. The first solution to interacting with two completely non-relational classes is to modify the interfaces of the respective classes, but what if you can't modify the source code or otherwise cause the interface to change? In this case, we tend to use a Adapter, between the two interfaces to create an adhesive interface, the original can not collaborate on the compatibility of the class, and do not have to modify the original two module code, in line with the open and closed principle.
PS: With the technology of interest in the same shoe plus group 5,446,459,721 Exchange
Total catalog of design patterns
Java/android design mode Learning Notes directory
features
The adapter mode converts the interface of one class to another interface that the client expects, so that two classes that would otherwise not work together because of an interface mismatch can work together.
Therefore, this pattern can be created by creating an adapter for interface conversion, which makes incompatible interfaces compatible, which allows the customer to decouple. If, after a period of time, we want to change the interface, the adapter can encapsulate the changed parts, and the customer doesn't have to change every time to deal with the different interfaces.
The adapter pattern can be used in the following scenarios:
- The system needs to use the existing classes, and such interfaces do not meet the needs of the system, that is, the interface is incompatible;
- You want to create a reusable class that works with some classes that are not much related to each other, including some that might be introduced in the future;
- A unified output interface is required, and the type of the input terminal is unpredictable.
UML class Diagram
The adapter pattern has "two" ways in the actual use: Object adapters and Class adapters.
Class Adapter Mode
First look at the UML class diagram of the class adapter pattern:
The class adapter implements the interface transformation by implementing the ITarget interface and inheriting the Adaptee class, which requires the operation of the Operation1 (), and the Adaptee class can only provide a operation2 () operation, so there is a case of incompatibility, when Adapter implements a Operation1 () function that converts adaptee operation2 () to the operation required by ITarget for compatibility. The class adapter pattern has three roles:
- Target: The destination role, which is the desired interface, because the class adapter pattern is discussed here, the target cannot be a class;
- Adaptee: The interface that needs to be adapted now;
- Adapter: Adapter role, the adapter converts the source interface into a target interface, so this role must be a specific class.
Object Adapter Mode
Object Adapter mode UML class diagram:
The UML class diagram and the class adapter pattern are basically the same, the difference is that the object adapter pattern and the adaptee relationship is Dependency, and the class adapter is generalization, one is dependent, and one is inheritance. So the Adapter class holds a reference to the Adaptee object, and the Operation1 () method links the Adaptee object to the associated operation of the ITarget interface.
This implementation directly to the object to be adapted to the Adapter, using a combination of the form of interface-compatible effect, this mode is more flexible than the class adapter mode, it is another benefit is that the method in the adaptation object is not exposed, and the class adapter because of the inheritance of the adaptation object, so, Functions that are adapted to the object class are also included in the Adapter class, which makes the Adapter class appear with some strange interfaces for use at higher cost. Therefore, the object adapter mode is more flexible and practical.
Compare
The class adapter pattern uses inherited methods, whereas the object adapter pattern uses a combined method. From the point of view of design patterns, the object adapter pattern follows the OO design principle of "multi-use combination, less inheritance", which is an advantage, but the class adapter pattern has the advantage that it does not need to re-implement the entire adapter behavior, after all, the class adapter pattern uses the way of inheritance, Of course, the disadvantage of this is the loss of the use of the combination of elasticity.
So in practice, depending on the usage, if the behavior of the Adaptee class is complex, but the Adapter adapter class does not require these most unrelated behaviors, it is appropriate to use the object adapter pattern, but if you need to re-implement most of the adaptee behavior, Then consider whether you want to use class adapter mode.
Example and source code
Class Adapter Mode
For example, we use the British triangular sockets in Hong Kong and the triangular sockets in the mainland as examples to construct the class adapter pattern, first of all the two socket format classes:
Ichinaoutlet.class
publicinterface IChinaOutlet { publicgetChinaType();}
Chinaoutlet.class
publicclass ChinaOutlet implements IChinaOutlet{ @Override publicgetChinaType() { return"Chinese three - pin socket"; }}
The above is the output format of the Chinese socket, then the British socket output format in Hong Kong:
Hkoutlet.class
publicclass HKOutlet { publicgetHKType() { return"British three - pin socket"; }}
In order to convert the British socket in Hong Kong into a Chinese socket, we need to construct a Adapter class to convert the socket format:
Outletadapter.class
publicclass OutletAdapter extends HKOutlet implements IChinaOutlet{ @Override publicgetChinaType() { String type = getHKType(); type = type.replace("Chinese""British"); return type; }}
This enables the conversion of the socket interface, the example is very simple and clear. Of course, this example is very simple, want to learn the idea: The original class is not modified on the basis of the original class after the expansion of the use of the new target system.
Object Adapter Mode
Object Adapter mode as an example of a view I wrote a few years ago: Android A carousel effect container viewgroup, this example is the typical "need a unified output interface, and the type of the input is unpredictable" situation, need to output is a view, The input data is not known. The original approach was to add a child view using dynamic AddChild and then delete the child view using the RemoveChild method:
... Public void AddChild(FinalView view)throwsnumberoverflowexception{if(Childnum < Maxnum) {//Recalculate the location array each time a child view is addedLocation.add (NewFloatwithflag ()); Turnplateviewutil.getlocationbynum (location); View.setonclicklistener (NewOnclicklistener () {@Override Public void OnClick(View arg0) {Listener.onclick (String) Arg0.gettag ()); } }); View.setonlongclicklistener (NewOnlongclicklistener () {@Override Public Boolean Onlongclick(View arg0) {Initpopupwindow (); Window.showasdropdown (arg0); Viewisbeinglongclick = arg0;return false; } }); AddView (view); childnum++; }Else{Throw NewNumberoverflowexception (Maxnum); }} Public void RemoveChild(FinalView view) {Try{ This. Removeview (view); Location.remove (0); childnum--; Turnplateviewutil.getlocationbynum (location); Requestlayout (); }Catch(Exception e) { }}...
The use of this method will cause external sub-View manipulation is very cumbersome, transposition think about, if the ListView needs to AddView and Removeview way to deal with, it is extremely headache, so now we can change a thinking to improve, learning the Adap of the ListView Ter thought, we also use the way of the adapter processing, in order to facilitate the direct inheritance baseadapter here, the modified code is as follows:
/** * Set adapter * @param Adapter */ Public void Setadapter(Baseadapter adapter)throwsnumberoverflowexception { This. adapter = adapter;if(Adapter.getcount () > Max_num) {Throw NewNumberoverflowexception (Adapter.getcount ()); } adapter.registerdatasetobserver (NewDatasetobserver () {@Override Public void onChanged() {Super. onChanged (); Ondatasetchanged (); }@Override Public void oninvalidated() {Super. oninvalidated (); Ondatasetchanged (); } }); Initchild ();}/** * Data source changed, need to redraw layout */Private void ondatasetchanged() {initchild ();} ...Private void Initchild() {removeallviews (); Location.clear (); for(intI=0; I < Adapter.getcount (); i++) {//Recalculate the location array each time a child view is addedLocation.add (NewFloatwithflag ()); Turnplateviewutil.getlocationbynum (location); View view = Adapter.getview (i,NULL, This); View.settag (i); View.setonclicklistener (NewOnclicklistener () {@Override Public void OnClick(View arg0) {Listener.onclick (String) Arg0.gettag ()); } }); View.setonlongclicklistener (NewOnlongclicklistener () {@Override Public Boolean Onlongclick(View arg0) {Initpopupwindow (); Window.showasdropdown (arg0); Viewisbeinglongclick = arg0;return false; } }); AddView (view); }}
The external use directly inherits the Baseadapter class, then returns the corresponding View in the corresponding method, thus realizes "the different input, the same output":
Private class turnplateviewadapter extends baseadapter{ @Override Public int GetCount() {return 5; }@Override PublicObjectGetItem(intPosition) {return NULL; }@Override Public Long Getitemid(intPosition) {return 0; }@Override PublicViewGetView(intPosition, View Convertview, ViewGroup parent) {Finaldrawable drawable = Getresources (). getdrawable (R.mipmap.ic_launcher); Drawable.setbounds (0,0, Drawable.getminimumheight (), Drawable.getminimumheight ()); TextView TextView =NewTextView (mainactivity. This); Textview.settextcolor (Getresources (). GetColor (Android. R.color.white)); Textview.settext (R.string.text); Textview.setcompounddrawables (NULL, Drawable,NULL,NULL); Textview.settag (tag++ +"");returnTextView }}
In this way, after the external modification of the input data, notify the adapter data source changes, because the Observer has been registered, so Turnplateview can naturally receive notifications, and refresh the interface, and finally achieve the same effect as before:
From this, in the initial learning of Android, the ListView adapter know how to use, but did not go into why so use, in fact, many places are the idea of design patterns, the source is really a first-hand learning materials.
Summary
The classic implementation of the Adapter model is to combine interfaces that are inherently incompatible, so that they can work well together. However, in the actual development, the Adapter model will be able to make appropriate changes according to the actual situation, the most typical is the ListView and Recyclerview, this design method makes the entire UI architecture becomes very flexible, can embrace change. So in actual use, follow the three scenarios mentioned above:
- The system needs to use the existing classes, and such interfaces do not meet the needs of the system, that is, the interface is incompatible;
- You want to create a reusable class that works with some classes that are not much related to each other, including some that might be introduced in the future;
- A unified output interface is required, and the type of the input terminal is unpredictable.
Depending on the situation, the adapter pattern is flexibly applied to the actual development.
Summing up, the advantages of the Adapter model are basically clear:
- Better reusability
The system needs to use the existing classes, and such interfaces do not meet the needs of the system, then through the adapter mode can be used to better reuse these functions;
- Better extensibility
When implementing the adapter functionality, you can invoke the features you have developed to naturally extend the functionality of the system.
Summing up is the open and closed principle of opening and closing the changes.
Of course, the adapter mode has some shortcomings, if in a system too much use of adapter mode, will make the system very messy, not easy to grasp the overall. For example, clearly see the call is a interface, in fact, the interior is adapted to the implementation of class B, so that the maintenance of increased, too much use is not necessary, rather than directly to the system reconstruction.
Source Download
Https://github.com/zhaozepeng/Design-Patterns/tree/master/AdapterPattern
References
Http://www.android100.org/html/201506/20/155883.html
Https://en.wikipedia.org/wiki/Adapter_pattern
Java/android Design Patterns Learning notes (6)---adapter mode