Goodle Clean设计架构

Goodle Clean设计架构

23  * @param <P> the response type
24  */
25 public abstract class UseCase<Q extends UseCase.RequestValues, P extends UseCase.ResponseValue> {
26
27     private Q mRequestValues;
28
29     private UseCaseCallback<P> mUseCaseCallback;
30
31     public void setRequestValues(Q requestValues) {
32         mRequestValues = requestValues;
33     }
34
35     public Q getRequestValues() {
36         return mRequestValues;
37     }
38
39     public UseCaseCallback<P> getUseCaseCallback() {
40         return mUseCaseCallback;
41     }
42
43     public void setUseCaseCallback(UseCaseCallback<P> useCaseCallback) {
44         mUseCaseCallback = useCaseCallback;
45     }
46
47     void run() {
48        executeUseCase(mRequestValues);
49     }
50
51     protected abstract void executeUseCase(Q requestValues);
52
53     /**
54      * Data passed to a request.
55      */
56     public interface RequestValues {
57     }
58
59     /**
60      * Data received from a request.
61      */
62     public interface ResponseValue {
63     }
64
65     public interface UseCaseCallback<R> {
66         void onSuccess(R response);
67         void onError();
68     }
69 }

  实体基类UseCase的设计用了泛型和接口,仅仅设计了两个字段mRequestValues和mUseCaseCallback。其中,mRequestValues代表数据请求参数,用泛型进行了封装,它其实也是一个类的对象;mUseCaseCallback代表请求结果,同样的,它也是一个类的对象,只不过这个类是用接口的形式进行抽象和封装的。同时,UseCase中定义抽象方法executeUseCase()作为实体操作的入口。

  接下来,我们随便看一个UseCase的实现类,就拿ActivateTask来说,ActivateTask继承了UseCase,其实现代码如下:

 1 /*
 2  * Copyright 2016, The Android Open Source Project
 3  *
 4  * Licensed under the Apache License, Version 2.0 (the "License");
 5  * you may not use this file except in compliance with the License.
 6  * You may obtain a copy of the License at
 7  *
 8  *      http://www.apache.org/licenses/LICENSE-2.0
 9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.example.android.architecture.blueprints.todoapp.tasks.domain.usecase;
18
19 import android.support.annotation.NonNull;
20
21 import com.example.android.architecture.blueprints.todoapp.UseCase;
22 import com.example.android.architecture.blueprints.todoapp.data.source.TasksRepository;
23
24 import static com.google.common.base.Preconditions.checkNotNull;
25
26 /**
27  * Marks a task as active (not completed yet).
28  */
29 public class ActivateTask extends UseCase<ActivateTask.RequestValues, ActivateTask.ResponseValue> {
30
31     private final TasksRepository mTasksRepository;
32
33     public ActivateTask(@NonNull TasksRepository tasksRepository) {
34         mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null!");
35     }
36
37     @Override
38     protected void executeUseCase(final RequestValues values) {
39         String activeTask = values.getActivateTask();
40         mTasksRepository.activateTask(activeTask);
41         getUseCaseCallback().onSuccess(new ResponseValue());
42     }
43
44     public static final class RequestValues implements UseCase.RequestValues {
45
46         private final String mActivateTask;
47
48         public RequestValues(@NonNull String activateTask) {
49             mActivateTask = checkNotNull(activateTask, "activateTask cannot be null!");
50         }
51
52         public String getActivateTask() {
53             return mActivateTask;
54         }
55     }
56
57     public static final class ResponseValue implements UseCase.ResponseValue { }
58 }

  可以看到,在ActivateTask 中,实现了父类UseCase的两个接口RequestValues 和ResponseValue ,这两个类将分别作为最终的实体请求对象类和返回结果对象类,同时,UseCase中的抽象方法executeUseCase()也被实现。因为实现的代码里面加入了泛型和接口,所以看起来会比较复杂,但是说到底无非就是继承和实现的关系,仅此而已。通过这种面向接口的设计方式,可以让我们的代码看起来结构更清晰、更统一。

  接下来,我们可以看一下这个项目中的任务执行类UseCaseThreadPoolScheduler,同样,UseCaseThreadPoolScheduler的设计采用了面向接口的方式,它实现了seCaseScheduler接口,UseCaseScheduler和UseCaseThreadPoolScheduler的实现分别如下:

 1 /*
 2  * Copyright 2016, The Android Open Source Project
 3  *
 4  * Licensed under the Apache License, Version 2.0 (the "License");
 5  * you may not use this file except in compliance with the License.
 6  * You may obtain a copy of the License at
 7  *
 8  *      http://www.apache.org/licenses/LICENSE-2.0
 9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.example.android.architecture.blueprints.todoapp;
18
19 /**
20  * Interface for schedulers, see {@link UseCaseThreadPoolScheduler}.
21  */
22 public interface UseCaseScheduler {
23
24     void execute(Runnable runnable);
25
26     <V extends UseCase.ResponseValue> void notifyResponse(final V response,
27             final UseCase.UseCaseCallback<V> useCaseCallback);
28
29     <V extends UseCase.ResponseValue> void onError(
30             final UseCase.UseCaseCallback<V> useCaseCallback);
31 }

 1 /*
 2  * Copyright 2016, The Android Open Source Project
 3  *
 4  * Licensed under the Apache License, Version 2.0 (the "License");
 5  * you may not use this file except in compliance with the License.
 6  * You may obtain a copy of the License at
 7  *
 8  *      http://www.apache.org/licenses/LICENSE-2.0
 9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.example.android.architecture.blueprints.todoapp;
18
19 import android.os.Handler;
20
21 import java.util.concurrent.ArrayBlockingQueue;
22 import java.util.concurrent.Executors;
23 import java.util.concurrent.ThreadPoolExecutor;
24 import java.util.concurrent.TimeUnit;
25
26 /**
27  * Executes asynchronous tasks using a {@link ThreadPoolExecutor}.
28  * <p>
29  * See also {@link Executors} for a list of factory methods to create common
30  * {@link java.util.concurrent.ExecutorService}s for different scenarios.
31  */
32 public class UseCaseThreadPoolScheduler implements UseCaseScheduler {
33
34     private final Handler mHandler = new Handler();
35
36     public static final int POOL_SIZE = 2;
37
38     public static final int MAX_POOL_SIZE = 4;
39
40     public static final int TIMEOUT = 30;
41
42     ThreadPoolExecutor mThreadPoolExecutor;
43
44     public UseCaseThreadPoolScheduler() {
45         mThreadPoolExecutor = new ThreadPoolExecutor(POOL_SIZE, MAX_POOL_SIZE, TIMEOUT,
46                 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(POOL_SIZE));
47     }
48
49     @Override
50     public void execute(Runnable runnable) {
51         mThreadPoolExecutor.execute(runnable);
52     }
53
54     @Override
55     public <V extends UseCase.ResponseValue> void notifyResponse(final V response,
56             final UseCase.UseCaseCallback<V> useCaseCallback) {
57         mHandler.post(new Runnable() {
58             @Override
59             public void run() {
60                 useCaseCallback.onSuccess(response);
61             }
62         });
63     }
64
65     @Override
66     public <V extends UseCase.ResponseValue> void onError(
67             final UseCase.UseCaseCallback<V> useCaseCallback) {
68         mHandler.post(new Runnable() {
69             @Override
70             public void run() {
71                 useCaseCallback.onError();
72             }
73         });
74     }
75
76 }

  可以看出,UseCaseThreadPoolScheduler实现了UseCaseScheduler中的三个抽象方法。

  接下来,我们再看看UseCaseHandler这个类,在UseCaseHandler中,通过子类实例化父类的形式,用UseCaseThreadPoolScheduler实例化了UseCaseScheduler对象。UseCaseHandler的代码如下:

/*
 * Copyright 2016, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.architecture.blueprints.todoapp;

import com.example.android.architecture.blueprints.todoapp.util.EspressoIdlingResource;

/**
 * Runs {@link UseCase}s using a {@link UseCaseScheduler}.
 */
public class UseCaseHandler {

    private static UseCaseHandler INSTANCE;

    private final UseCaseScheduler mUseCaseScheduler;

    public UseCaseHandler(UseCaseScheduler useCaseScheduler) {
        mUseCaseScheduler = useCaseScheduler;
    }

    public <T extends UseCase.RequestValues, R extends UseCase.ResponseValue> void execute(
            final UseCase<T, R> useCase, T values, UseCase.UseCaseCallback<R> callback) {
        useCase.setRequestValues(values);
        useCase.setUseCaseCallback(new UiCallbackWrapper(callback, this));

        // The network request might be handled in a different thread so make sure
        // Espresso knows
        // that the app is busy until the response is handled.
        EspressoIdlingResource.increment(); // App is busy until further notice

        mUseCaseScheduler.execute(new Runnable() {
            @Override
            public void run() {

                useCase.run();
                // This callback may be called twice, once for the cache and once for loading
                // the data from the server API, so we check before decrementing, otherwise
                // it throws "Counter has been corrupted!" exception.
                if (!EspressoIdlingResource.getIdlingResource().isIdleNow()) {
                    EspressoIdlingResource.decrement(); // Set app as idle.
                }
            }
        });
    }

    public <V extends UseCase.ResponseValue> void notifyResponse(final V response,
            final UseCase.UseCaseCallback<V> useCaseCallback) {
        mUseCaseScheduler.notifyResponse(response, useCaseCallback);
    }

    private <V extends UseCase.ResponseValue> void notifyError(
            final UseCase.UseCaseCallback<V> useCaseCallback) {
        mUseCaseScheduler.onError(useCaseCallback);
    }

    private static final class UiCallbackWrapper<V extends UseCase.ResponseValue> implements
            UseCase.UseCaseCallback<V> {
        private final UseCase.UseCaseCallback<V> mCallback;
        private final UseCaseHandler mUseCaseHandler;

        public UiCallbackWrapper(UseCase.UseCaseCallback<V> callback,
                UseCaseHandler useCaseHandler) {
            mCallback = callback;
            mUseCaseHandler = useCaseHandler;
        }

        @Override
        public void onSuccess(V response) {
            mUseCaseHandler.notifyResponse(response, mCallback);
        }

        @Override
        public void onError() {
            mUseCaseHandler.notifyError(mCallback);
        }
    }

    public static UseCaseHandler getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new UseCaseHandler(new UseCaseThreadPoolScheduler());
        }
        return INSTANCE;
    }
}

  从上面的代码中,我们可以看到,声明的变量mUseCaseScheduler是UseCaseScheduler的对象,但是在构建UseCaseHandler对象的时候,传入的参数却是UseCaseThreadPoolScheduler对象,即用UseCaseThreadPoolScheduler实例化了UseCaseScheduler对象。然后,对mUseCaseScheduler的所有操作都转化成了对UseCaseThreadPoolScheduler对象的操作。

  然后,我们仔细看UseCaseHandler的实现的代码,我们会发现其实对实体进行操作的入口就是execute()方法!因为这个方法里面调用了UseCase的run(),而UseCase的run()最终调用了UseCase的executeUseCase()。通过刚刚的分析,我们应该知道,我们实际上操作的实体应该是UseCase的实现类,而不是UseCase类本身,那么这中间是通过什么方式将对UseCase的操作转移到UseCase的实现类上面的呢?我们会发现UseCaseHandler的execute()传入了UseCase对象作为参数,好的,那么我们就看看execute()是在哪里被调用的吧!

  经过追踪,我们看到在TasksPresenter类中调用了此方法,调用处的代码如下:

 1 @Override
 2     public void activateTask(@NonNull Task activeTask) {
 3         checkNotNull(activeTask, "activeTask cannot be null!");
 4         mUseCaseHandler.execute(mActivateTask, new ActivateTask.RequestValues(activeTask.getId()),
 5                 new UseCase.UseCaseCallback<ActivateTask.ResponseValue>() {
 6                     @Override
 7                     public void onSuccess(ActivateTask.ResponseValue response) {
 8                         mTasksView.showTaskMarkedActive();
 9                         loadTasks(false, false);
10                     }
11
12                     @Override
13                     public void onError() {
14                         mTasksView.showLoadingTasksError();
15                     }
16                 });
17     }

  可以看到,我们传入的参数实际上是UseCase的实现类ActivateTask的对象,到这里,我们就明白啦!原来也是子类实例化父类的方式。

  上面我只是简单粗略地讲述了一下项目中部分模块的代码,仅仅是举个例子,更多的东西需要大家自己用面向对象的思想去理解。我说这些的目的就是想告诉大家,充分运面向对象的思想就可以设计出很多看似复杂的架构和项目,但是不管再怎么复杂的代码也肯定是有迹可循的,我们只要抓住了这些设计思想的本质,多看几遍代码,一定会豁然开朗!

时间: 2024-10-05 05:06:56

Goodle Clean设计架构的相关文章

Android App的设计架构:MVC,MVP,MVVM与架构经验谈

来源: Android App的设计架构:MVC,MVP,MVVM与架构经验谈 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开发中,很多人经常会头疼于App的架构如何设计: 我的App需要应用这些设计架构吗? MVC,MVP等架构讲的是什么?区别是什么? 本文就来带你分析一下这几个架构的特性,优缺点,以及App架构设计中应该注意的问题. 1.架构设计的目的 通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合.这样做的好处是使得程序在开发的过程中,开发人员

尚学堂_java300集笔记_jdbc设计架构

264.jdbc_mysql安装和启动_安装问题的解决 265.jdbc_mysql_navicate客户端软件_建库_建表_自增主键_sql执行 266.jdbc_mysql_环境变量配置_命令行模式操作 mysql是一种开放源代码的关系型数据库管理系统(RDBMS):目前很多大公司(新浪.京东.阿里等)都在使用:适用于所有的平台:支持多线程,充分利用CPU资源,性能很出色:价格便宜:大数据处理(对某些包含50000000个记录的数据库使用mysql完全没有问题):使用最多的版本是5.5 my

软件设计架构

微信.陌陌等著名IM软件设计架构详解 http://wenku.it168.com/wenji/825 架构无小事:QQ碰微信 贴吧遇微博

PHP发明人谈MVC和网站设计架构

PHP是全世界上使用率最高的网页开发语言,台湾每4个网站,就有1个用PHP语言开发.1995年发明PHP语言的Rasmus Lerdorf,也是打造出Yahoo全球服务网站的架构师之一,他首度来台分享如何架构网站扩充性丶安全性和效能的秘诀. Q:越来越多Web 2.0网站走向应用平台,你认为打造这类平台的关键为何? A:简单来看,应用平台就是API,任何Ajax或 Web 2.0类型的网站,都是在应用平台上运用了API来创造出视觉介面的互动效果.例如Yahoo Mail,透过简单的Request

Kubernetes系列02—Kubernetes设计架构和设计理念

1.Kubernetes设计架构 Kubernetes集群包含有节点代理kubelet和Master组件(APIs, scheduler, etc),一切都基于分布式的存储系统.下面这张图是Kubernetes的架构图. 2.Kubernetes节点 2.1 介绍 ① 在这张系统架构图中,我们把服务分为运行在工作节点上的服务和组成集群级别控制板的服务. ② Kubernetes节点有运行应用容器必备的服务,而这些都是受Master的控制. ③ 每次个节点上当然都要运行Docker.Docker来

kubernetes之三---Kubernetes设计架构和设计理念

1.kubernetes设计架构 k8s基础集群环境主要是运行kubernetes管理端服务以及node节点上的服务部署及使用. Kubernetes设计架构文档:https://www.kubernetes.org.cn/kubernetes%E8%AE%BE%E8%AE%A1%E6%9E%B6%E6%9E%84 Kubernetes集群包含有节点代理kubelet和Master组件(APIs, scheduler, etc),一切都基于分布式的存储系统.下面这张图是Kubernetes的架构

领域驱动设计架构风格

领域驱动设计 (DDD) 是面向对象的软件设计方法,基于业务领域.元素和行为,以及它们之间的关系.其目标是将潜在业务领域的实现用业务领域专家语言定义的领域模型来表达出来.领域模型可以看一个框架,让业务变得有条理的解决方案. 要应用领域驱动设计,您必须对您想建模的业务领域有很了解, 或者熟练掌握这些业务知识.开发团队将经常与业务领域专家合作来创建模型.架构师,开发人员和主题专家有着不同的背景,在许多环境中将使用不同的语言来描述他们的目标,设计和要求. 而在域驱动设计中,整个团队统一使用一种专注于业

一张图看Google MVP设计架构

这段时间看了一下Google官方推出的MVP架构案例,决定把对MVP的理解用类图的形式表述一下.MVP架构的设计思想确实非常值得学习,大家如果还不是很了解MVP,建议抽时间去研究研究,相信对大家的架构设计能力和编码能力都会有所提高.当然,除了Google官方的案例,网上也有很多关于MVP架构的技术文章和案例,大家可以搜一搜,看一看,学习学习!好了,我就不赘述MVP的设计思想了,直接上图! 以上就是我对Google MVP架构的一个简单认识,目前可能还理解得不够深刻,如果以后有了更深刻的领悟,我会

[架构设计] 架构设计文章分享链接集合 —— 文章来源圣殿骑士博客

昨天在CNB的置顶推荐上看到了@圣殿骑士 的<架构设计分享之权限系统(看图说话)>这篇文章,大概的阅读完之后被@圣殿骑士强大功力惊呆了,记录一下他部分关于架构的文章链接 文章来源:圣殿骑士 架构设计分享之权限系统(看图说话) 架构设计(ASP.NET MVC+Knockout+Web API+SignalR) 31天重构学习笔记重新整理下载