Slide 1

Slide 1 text

Proxy Pattern ayangxu 2016/01/07

Slide 2

Slide 2 text

A proxy, in its most general form, is a class functioning as an interface to something else.

Slide 3

Slide 3 text

Network (retrofit)

Slide 4

Slide 4 text

REST API interface WRLoginService {
 @JSONEncoded
 @POST("/login")
 Observable login(
 @JSONField("code") String code,
 @JSONField("deviceId") String deviceId,
 @JSONField("wxToken") Integer wxToken
 );
 }

Slide 5

Slide 5 text

REST API interface WRLoginService {
 @JSONEncoded
 @POST("/login")
 Observable login(
 @JSONField("code") String code,
 @JSONField("deviceId") String deviceId,
 @JSONField("wxToken") Integer wxToken
 );
 } LoginInfo loginInfo = RestAdapter#create(WRLoginService.class).login(/** */);

Slide 6

Slide 6 text

REST API interface WRLoginService {
 @JSONEncoded
 @POST("/login")
 Observable login(
 @JSONField("code") String code,
 @JSONField("deviceId") String deviceId,
 @JSONField("wxToken") Integer wxToken
 );
 } LoginInfo loginInfo = RestAdapter#create(WRLoginService.class).login(/** */); login() 构造URL 发请求 JSON 反序列列化

Slide 7

Slide 7 text

EventBus (Watcher)

Slide 8

Slide 8 text

EventBus 是什什么 • 发布-订阅模型(Publish - Subscribe) • guava/EventBus • greenrobot/EventBus • square/otto • moai/Watcher

Slide 9

Slide 9 text

// Define events: public class MessageEvent { /* Additional fields if needed */ } // Prepare subscribers: eventBus.register(this); public void onEvent(AnyEventType event) { /* Do something */ }; // Post events: eventBus.post(event); greenrobot/EventBus

Slide 10

Slide 10 text

// Define events: public class MessageEvent { /* Additional fields if needed */ } // Prepare subscribers: eventBus.register(this); public void onEvent(AnyEventType event) { /* Do something */ }; // Post events: eventBus.post(event); greenrobot/EventBus // Define events: public class MessageEvent { /* Additional fields if needed */ } // Prepare subscribers: eventBus.register(this); public void onEvent(AnyEventType event) { /* Do something */ }; // Post events: eventBus.post(event);

Slide 11

Slide 11 text

Bus bus = new Bus(); bus.post(new AnswerAvailableEvent(42)); @Subscribe public void answerAvailable(AnswerAvailableEvent event) { // TODO: React to the event somehow! } bus.register(this); @Produce public AnswerAvailableEvent produceAnswer() { // Assuming 'lastAnswer' exists. return new AnswerAvailableEvent(this.lastAnswer); } square/otto

Slide 12

Slide 12 text

Bus bus = new Bus(); bus.post(new AnswerAvailableEvent(42)); @Subscribe public void answerAvailable(AnswerAvailableEvent event) { // TODO: React to the event somehow! } bus.register(this); @Produce public AnswerAvailableEvent produceAnswer() { // Assuming 'lastAnswer' exists. return new AnswerAvailableEvent(this.lastAnswer); } square/otto Bus bus = new Bus(); bus.post(new AnswerAvailableEvent(42)); @Subscribe public void answerAvailable(AnswerAvailableEvent event) { // TODO: React to the event somehow! } bus.register(this); @Produce public AnswerAvailableEvent produceAnswer() { // Assuming 'lastAnswer' exists. return new AnswerAvailableEvent(this.lastAnswer); }

Slide 13

Slide 13 text

// Define an Event public interface PushWatcher extents Watchers.Watcher { void notify(Message message); } // Publishing an Event Watchers.of(PushWatcher.class).notify(message); // Subscribing to an Event public class MyFragment extends Fragment implement PushWatcher { public void notify(Message message) { } public void onStart() { Watchers.bind(this); } } Watcher

Slide 14

Slide 14 text

// Define an Event public interface PushWatcher extents Watchers.Watcher { void notify(Message message); } // Publishing an Event Watchers.of(PushWatcher.class).notify(message); // Subscribing to an Event public class MyFragment extends Fragment implement PushWatcher { public void notify(Message message) { } public void onStart() { Watchers.bind(this); } } Watcher // Define an Event public interface PushWatcher extents Watchers.Watcher { void notify(Message message); } // Publishing an Event Watchers.of(PushWatcher.class).notify(message); // Subscribing to an Event public class MyFragment extends Fragment implement PushWatcher { public void notify(Message message) { } public void onStart() { Watchers.bind(this); } }

Slide 15

Slide 15 text

Watchers.of(PushWatcher.class).notify(message); 调⽤用委托

Slide 16

Slide 16 text

Watchers.of(PushWatcher.class).notify(message); 调⽤用委托 Watchers.of(PushWatcher.class).notify(message);

Slide 17

Slide 17 text

调⽤用委托 Watchers.of(PushWatcher.class).notify(message); EventBus

Slide 18

Slide 18 text

调⽤用委托 Watchers.of(PushWatcher.class).notify(message); EventBus 事件类别

Slide 19

Slide 19 text

调⽤用委托 Watchers.of(PushWatcher.class).notify(message); EventBus 事件类别 事件动作

Slide 20

Slide 20 text

调⽤用委托 Watchers.of(PushWatcher.class).notify(message); EventBus 事件类别 事件动作 动作上下⽂文

Slide 21

Slide 21 text

Proxy.newProxyInstance( clazz.getClassLoader(), new Class[] { clazz }, new WatcherHandler(clazz) ) 调⽤用委托

Slide 22

Slide 22 text

Proxy.newProxyInstance( clazz.getClassLoader(), new Class[] { clazz }, new WatcherHandler(clazz) ) 调⽤用委托 Proxy.newProxyInstance( clazz.getClassLoader(), new Class[] { clazz }, new WatcherHandler(clazz) )

Slide 23

Slide 23 text

WatcherHandler static class WatcherHandler implements InvocationHandler {
 private final Class clazz;
 WatcherHandler(Class clazz) {
 this.clazz = clazz;
 }
 
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 if (method.getDeclaringClass() == Object.class) {
 return method.invoke(this, args);
 }
 instance.trigger(clazz, method, args);
 return null;
 }
 }

Slide 24

Slide 24 text

WatcherHandler static class WatcherHandler implements InvocationHandler {
 private final Class clazz;
 WatcherHandler(Class clazz) {
 this.clazz = clazz;
 }
 
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 if (method.getDeclaringClass() == Object.class) {
 return method.invoke(this, args);
 }
 instance.trigger(clazz, method, args);
 return null;
 }
 } static class WatcherHandler implements InvocationHandler {
 private final Class clazz;
 WatcherHandler(Class clazz) {
 this.clazz = clazz;
 }
 
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 if (method.getDeclaringClass() == Object.class) {
 return method.invoke(this, args);
 }
 instance.trigger(clazz, method, args);
 return null;
 }
 } EventBus

Slide 25

Slide 25 text

WatcherHandler static class WatcherHandler implements InvocationHandler {
 private final Class clazz;
 WatcherHandler(Class clazz) {
 this.clazz = clazz;
 }
 
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 if (method.getDeclaringClass() == Object.class) {
 return method.invoke(this, args);
 }
 instance.trigger(clazz, method, args);
 return null;
 }
 } static class WatcherHandler implements InvocationHandler {
 private final Class clazz;
 WatcherHandler(Class clazz) {
 this.clazz = clazz;
 }
 
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 if (method.getDeclaringClass() == Object.class) {
 return method.invoke(this, args);
 }
 instance.trigger(clazz, method, args);
 return null;
 }
 } EventBus 事件类别

Slide 26

Slide 26 text

WatcherHandler static class WatcherHandler implements InvocationHandler {
 private final Class clazz;
 WatcherHandler(Class clazz) {
 this.clazz = clazz;
 }
 
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 if (method.getDeclaringClass() == Object.class) {
 return method.invoke(this, args);
 }
 instance.trigger(clazz, method, args);
 return null;
 }
 } static class WatcherHandler implements InvocationHandler {
 private final Class clazz;
 WatcherHandler(Class clazz) {
 this.clazz = clazz;
 }
 
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 if (method.getDeclaringClass() == Object.class) {
 return method.invoke(this, args);
 }
 instance.trigger(clazz, method, args);
 return null;
 }
 } EventBus 事件类别 事件动作

Slide 27

Slide 27 text

WatcherHandler static class WatcherHandler implements InvocationHandler {
 private final Class clazz;
 WatcherHandler(Class clazz) {
 this.clazz = clazz;
 }
 
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 if (method.getDeclaringClass() == Object.class) {
 return method.invoke(this, args);
 }
 instance.trigger(clazz, method, args);
 return null;
 }
 } static class WatcherHandler implements InvocationHandler {
 private final Class clazz;
 WatcherHandler(Class clazz) {
 this.clazz = clazz;
 }
 
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 if (method.getDeclaringClass() == Object.class) {
 return method.invoke(this, args);
 }
 instance.trigger(clazz, method, args);
 return null;
 }
 } EventBus 事件类别 事件动作 动作上下⽂文

Slide 28

Slide 28 text

// Define an Event public interface PushWatcher extents Watchers.Watcher { void notify(Message message); } // Publishing an Event Watchers.of(PushWatcher.class).notify(message); // Subscribing to an Event public class MyFragment extends Fragment implement PushWatcher { public void notify(Message message) { } public void onStart() { Watchers.bind(this); } } 类型安全 & 重构

Slide 29

Slide 29 text

// Define an Event public interface PushWatcher extents Watchers.Watcher { void notify(Message message); } // Publishing an Event Watchers.of(PushWatcher.class).notify(message); // Subscribing to an Event public class MyFragment extends Fragment implement PushWatcher { public void notify(Message message) { } public void onStart() { Watchers.bind(this); } } 类型安全 & 重构 // Define an Event public interface PushWatcher extents Watchers.Watcher { void notify(Message message); } // Publishing an Event Watchers.of(PushWatcher.class).notify(message); // Subscribing to an Event public class MyFragment extends Fragment implement PushWatcher { public void notify(Message message) { } public void onStart() { Watchers.bind(this); } }

Slide 30

Slide 30 text

A/B Testing (Feature)

Slide 31

Slide 31 text

功能定义 public interface Https extends Feature {
 String schema();
 }

Slide 32

Slide 32 text

两种实现 @BooleanValue(true) public static class HttpsOn implements Https {
 @Override
 public String schema() {
 return "https";
 }
 }
 
 @BooleanValue(false) public static class HttpsOff implements Https {
 @Override
 public String schema() {
 return "http";
 }
 }

Slide 33

Slide 33 text

使⽤用 new Endpoint() {
 @Override
 public String getUrl() {
 return Features.of(Https.class).schema()
 + "://" + Features.of(ServiceEndPoint.class).url();
 }
 };

Slide 34

Slide 34 text

开关 HttpsOn HttpsOff Https SP Server Features

Slide 35

Slide 35 text

reflect.Proxy if (!c.isInterface()) {
 throw new IllegalArgumentException(c + " is not an interface");
 }

Slide 36

Slide 36 text

Dexmaker https://github.com/crittercism/dexmaker

Slide 37

Slide 37 text

实现部分接⼝口 @GET("/review/list")
 Observable LoadTimeLine(
 @Query("listType") int listType,
 @Query("synckey") long synckey,
 @Query("maxIdx") long maxIdx,
 @Query("count") int count
 );

Slide 38

Slide 38 text

实现部分接⼝口 public Observable LoadAllTimeLineList() {
 return LoadTimeLine(
 ReviewListType.TIMELINE.getTypeCode(),
 0,
 0l,
 LOAD_REVIEW_LIST_COUNT_AT_ONCE
 ).map(new Func1() {
 @Override
 public AllTimeLineList call(TimelineList timeLineList) {
 return new AllTimeLineList(timeLineList);
 }
 });
 }

Slide 39

Slide 39 text

实现部分接⼝口 public Observable LoadFriendsTimeLineList(long synckey) {
 return LoadTimeLine(
 ReviewListType.TIMELINE_FRIEND.getTypeCode(),
 synckey,
 0l,
 LOAD_REVIEW_LIST_COUNT_AT_ONCE
 ).map(new Func1() {
 @Override
 public FriendsTimeLineList call(TimelineList timeLineList) {
 return new FriendsTimeLineList(timeLineList);
 }
 });
 }

Slide 40

Slide 40 text

Factory 代理理

Slide 41

Slide 41 text

Factory 代理理 okHttpClient.setSslSocketFactory(Reflections.proxy(WRApplicationContext.sharedInstance(),
 SSLSocketFactory.class, new InvocationHandler() {
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 if (method.getDeclaringClass() == Object.class) {
 return method.invoke(this, args);
 }
 method = FeatureSSLSocketFactory.class.getDeclaredMethod(
 method.getName(), method.getParameterTypes());
 return method.invoke(Features.of(FeatureSSLSocketFactory.class), args);
 }
 }));

Slide 42

Slide 42 text

JavaBeanProxy

Slide 43

Slide 43 text

JavaBeanProxy 需求点:设置过的值才提交(UpdateConfig)

Slide 44

Slide 44 text

JavaBeanProxy 需求点:设置过的值才提交(UpdateConfig) 问题:怎么知道哪个字段被设置过?

Slide 45

Slide 45 text

JavaBeanProxy

Slide 46

Slide 46 text

JavaBeanProxy JSON.toJSONString(object, new PropertyFilter() {
 @Override
 public boolean apply(Object o, String s, Object o1) {
 return JavaBeanProxy.has(o, s);
 }
 });

Slide 47

Slide 47 text

JavaBeanStorage

Slide 48

Slide 48 text

JavaBeanStorage 需求点:设置落地

Slide 49

Slide 49 text

JavaBeanStorage 需求点:设置落地 问题:怎么避免写⼀一堆重复代码?

Slide 50

Slide 50 text

JavaBeanStorage public void setDiscoverSyncKey(long syncKey) {
 setValue(AccountManager.getInstance().getCurrentLoginAccountId(),
 WRSettingKey.DISCOVER_SYNC_KEY, String.valueOf(syncKey));
 }
 
 public long getDiscoverSyncKey() {
 return getLongValue(WRSettingKey.DISCOVER_SYNC_KEY,
 AccountManager.getInstance().getCurrentLoginAccountId());
 }

Slide 51

Slide 51 text

JavaBeanStorage public void setReadingBookId(String bookId) {
 setValue(AccountManager.getInstance().getCurrentLoginAccountId(), 
 WRSettingKey.READING_BOOK_ID, bookId);
 }
 
 public String getReadingBookId() {
 return getStringValue(WRSettingKey.READING_BOOK_ID,
 AccountManager.getInstance().getCurrentLoginAccountId());
 }

Slide 52

Slide 52 text

JavaBeanStorage

Slide 53

Slide 53 text

JavaBeanStorage

Slide 54

Slide 54 text

Proxy 还能做什什么?