This series of articles is authorized by Ali God Anly_Jun
Antecedents feed
In the last video, Light used decorator mode to adjust the drink ingredients (sugar, ice, honey…). From now on, I am no longer afraid of all kinds of customer requirements. All kinds of drinks have also become a major feature of Xiaoguang Hot and dry noodle shop.
Of course, the drinks are not unlimited. As the tasting period was coming to an end, Xiao Guang discussed with her cousin. Considering the feedback from customers, they chose three of them. They still need to negotiate with the merchants to decide which one to use.
All sample source code has been uploaded to Github, poke here
The trouble of little light
As the negotiation with the supplier is approaching, Xiao Guang is getting nervous. In the past, it is to deal with computers, and less people, let alone shopping malls… Although he is the purchaser, it is a little empty.
Let’s take a look at the light to sign:
Public interface Person {/** * @param price */ void signing(int price); } // The light in my heart is hollow: Public class implements Person {@override public void signing(int price) {system.out.println (" XiaoGuang "+ price + "Price per case signed."); }}Copy the code
Dragon appearance
So, light to do building materials business cousin Dragon, let dragon help to negotiate. Tai Lung gladly accepted, with little light’s bottom line to go.
Public class implements Person {private Person Person; public DaLong(Person person) { this.person = person; } @override public void signing(int price) {system.out.println (" signing :" + price); if (price < 100) { this.person.signing(price); } else { negotiate(price); }} public void negotiate(int price) {system.out.println (" price "+ (price-80)); }}Copy the code
Dalong also inherits from Person and has the responsibility of signing orders. But in addition to signing, dragons are also responsible for negotiating. There are also some restrictions on the signature (the bottom line xiaoguang gave him is 100 per box). Of course, after the negotiation, the signature still needs to be signed by Xiaoguang.
Negotiations begin
Dalong, though not much older than Light, is a business veteran. After getting light’s bottom line, he cut another 20 from that, and went to negotiate with the drinks supplier.
public class Demo { public static void main(String[] args) { DaLong daLong = new DaLong(new XiaoGuang()); // First round, the price is 120. signing(120); // The second round, the other side offers 100. // The third round, the other side offer 90. }}Copy the code
Wine table, saw three rounds, won:
// Output Quote :120 not accepted, request reduction 40 Quoted :100 not accepted, request reduction 20 quoted :90 Xiaogang signed at 90 per case.Copy the code
As expected or dragon skill one-upmanship ah, than the light expected less price clinch a deal. Light is also learn a lot of skills… Bow down to Big Dragon brother.
After the story
As usual, after the story, we use UML class diagrams to tease out the above relationships:
Compared to the previous relationship, this is relatively simple, only two roles, Xiao Guang and Tai Lung, both implement the Person interface. The key point is:
- Dalong deals directly with suppliers, but the actual decisions and actions (signing orders) are made by Xiaoguang.
- That means Dalong is acting for Little Light.
This is the proxy pattern we are talking about: provide another object (light) with a proxy (big dragon) to control access to this object.
In our example, because Xiaoguang was too timid to negotiate directly with the supplier, he sent the agent Dalong to face the supplier.
Extended Reading 1
Careful students may have noticed that the pattern of this example seems to be somewhat similar to the decoration pattern mentioned above. Here dalong also decorates The light with new responsibilities (negotiate):
Public void negotiate(int price) {system.out.println (" negotiate "+ (price-80)); }Copy the code
So how is the proxy pattern different from the decorator pattern?
Let’s revisit both with a key note:
- The proxy pattern is designed to provide a proxy for an object to control access to that object.
- The decorator pattern is designed to dynamically add responsibilities to an object, increasing the behavior/properties of the object.
In both cases, though, the proxy class/decorator class actually calls the propped object/decorator. Whereas the proxy mode is about control, the decorator mode is about adding.
For example, in this case, tai Long does the signing for Light, but it’s not just a matter of adding certain behaviors/attributes like decoration mode. Tai Lung also added control:
Public void signing(int price) {system.out.println (" + price "); if (price < 100) { this.person.signing(price); } // If the price is greater than or equal to 100, dalong does not let go. else {negotiate(price); }}Copy the code
If the other side of the offer is greater than or equal to 100, big dragon and did not let the light processing. That means tai Lung is in control.
Extended Reading 2
It is mentioned above that Tai Lung has control, that is to say, this kind of agent is actually a control agent, which can also be called protection agent.
Proxy mode in addition to this control access/protection, commonly used scenarios include:
Remote proxy: Provides a local representation of an object in a different address space, thus hiding the fact that the proxied object exists in a different address space. Intelligent reference proxy: Perform additional operations on each operation of the prosteed object in the proxy, such as recording the number of times the prosteed object is referenced, etc. It’s kind of like reference counting.
Extension Reading 3
Speaking of remote agents, it’s worth talking about Android’s famous AIDL. For those familiar with AIDL, it should be clear that AIDL is a typical application of the remote proxy mode.
Create a simple AIDL file:
// IRemoteService.aidl
package com.anly.samples;
// Declare any non-default types here with import statements
interface IRemoteService {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void signing(int price);
}
Copy the code
The generated iremoteservice.java file is as follows:
/* * This file is auto-generated. DO NOT MODIFY. * Original file: /Users/mingjun/Dev/my_github/AndroidLessonSamples/app/src/main/aidl/com/anly/samples/IRemoteService.aidl */ package com.anly.samples; // Declare any non-default types here with import statements public interface IRemoteService extends android.os.IInterface { /** * Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.anly.samples.IRemoteService { private static final java.lang.String DESCRIPTOR = "com.anly.samples.IRemoteService"; /** * Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.anly.samples.IRemoteService interface, * generating a proxy if needed. */ public static com.anly.samples.IRemoteService asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin ! = null) && (iin instanceof com.anly.samples.IRemoteService))) { return ((com.anly.samples.IRemoteService) iin); } return new com.anly.samples.IRemoteService.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_signing: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); int _result = this.signing(_arg0); reply.writeNoException(); reply.writeInt(_result); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.anly.samples.IRemoteService { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public int signing(int price) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(price); mRemote.transact(Stub.TRANSACTION_signing, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_signing = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); } public int signing(int price) throws android.os.RemoteException; }Copy the code
AIDL automatically generated Java file format is messy, formatted a bit. There are a few key points:
- IRemoteService is an interface that has a signing method
- IRemoteService has a static abstract inner class Stub that implements the IRemoteService interface.
- Stub has an asInterface method that returns an IRemoteService, which is actually a Proxy.
- The Stub has a private inner class Proxy.
- The mechanism for this inner class is to increase cohesion. An AIDL-generated file is theoretically a business service architecture, so it is put together.
Let’s implement the Proxy and Stub, and then use UML diagrams to sort it out:
The client AidlSampleActivity:
// Get Proxy from the ServiceConnection binding service: public void onServiceConnected(ComponentName name, IBinder service) { mRemoteService = IRemoteService.Stub.asInterface(service); isBound = true; if (mRemoteService ! = null) { try { mCurrentPrice = mRemoteService.signing(mCurrentPrice); mResult.setText("Result:" + mCurrentPrice); } catch (RemoteException e) { e.printStackTrace(); }}}Copy the code
The RemoteService service inherits the IBinder generated by Stub:
private IRemoteService.Stub mBinder = new IRemoteService.Stub() { @Override public int signing(int price) throws RemoteException { int signingPrice = price - 10; Log.d("mingjun", "signing: " + signingPrice); return signingPrice; }};Copy the code
To make it clear that this is a remote proxy, we have added RemoteService to other processes:
<service android:name=".aidl.RemoteService" android:process="com.anly.other"/>
Copy the code
This article does not go into the application and principle of AIDL, the specific client (AidlSampleActivity) and service (RemoteService) code will not paste, complete code here. OK, that’s the proxy model we’re talking about today. With the agent mode, especially the remote agent, light found that sometimes they can not visit the store, there is more time to go out to investigate the new store address… Ha ha.
http://www.cniao5.com/forum/thread/96ee457e256c11e78c6c00163e0230fa
Attention to the public account free “N sets of client actual combat project tutorial”