面向对象-设计原则

来源:互联网 发布:网络平台承担连带责任 编辑:程序博客网 时间:2024/06/14 00:38

1.设计原则-之Volley


    (1)单一职责原则(S)

          定义:一个类有多个方法,多个方法应是相关的,有共同的职责。

          范围:适用于基础类,不适用于聚合类。聚合类应优先使用组合,再选择继承


          Cache类:

           1.获取缓存

           2.添加缓存

           3.初始化缓存

           4.废除缓存

           5.移除

/** * An interface for a cache keyed by a String with a byte array as data. */public interface Cache {    /**     * Retrieves an entry from the cache.     * @param key Cache key     * @return An {@link Entry} or null in the event of a cache miss     */    public Entry get(String key);    /**     * Adds or replaces an entry to the cache.     * @param key Cache key     * @param entry Data to store and metadata for cache coherency, TTL, etc.     */    public void put(String key, Entry entry);    /**     * Performs any potentially long-running actions needed to initialize the cache;     * will be called from a worker thread.     */    public void initialize();    /**     * Invalidates an entry in the cache.     * @param key Cache key     * @param fullExpire True to fully expire the entry, false to soft expire     */    public void invalidate(String key, boolean fullExpire);    /**     * Removes an entry from the cache.     * @param key Cache key     */    public void remove(String key);    /**     * Empties the cache.     */    public void clear();    /**     * Data and metadata for an entry returned by the cache.     */    public static class Entry {        /** The data returned from cache. */        public byte[] data;        /** ETag for cache coherency. */        public String etag;        /** Date of this response as reported by the server. */        public long serverDate;        /** TTL for this record. */        public long ttl;        /** Soft TTL for this record. */        public long softTtl;        /** Immutable response headers as received from server; must be non-null. */        public Map<String, String> responseHeaders = Collections.emptyMap();        /** True if the entry is expired. */        public boolean isExpired() {            return this.ttl < System.currentTimeMillis();        }        /** True if a refresh is needed from the original data source. */        public boolean refreshNeeded() {            return this.softTtl < System.currentTimeMillis();        }    }}


     

    (2) 开闭原则(O)

        定义:对修改关闭,对扩展开放。(A调用B,对A修改关闭,对B扩展开放),

                      提供者B增加功能,调用者A不要修改代码。

           范围:接口不变的情况之下
           原因:减少变化


public static RequestQueue newRequestQueueInDisk(Context context, String dir, HttpStack stack) {        File cacheDir = new File(dir, DEFAULT_CACHE_DIR);        String userAgent = "volley/0";        try {            String packageName = context.getPackageName();            PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);            userAgent = packageName + "/" + info.versionCode;        } catch (NameNotFoundException e) {        }        if (stack == null) {            if (Build.VERSION.SDK_INT >= 9) {                stack = new HurlStack();            } else {                // Prior to Gingerbread, HttpUrlConnection was unreliable.                // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));            }        }        Network network = new BasicNetwork(stack); //对修改关闭,对拓展开放        Cache cache =  new DiskBasedCache(cacheDir);//对修改关闭,对拓展开放        RequestQueue queue = new RequestQueue(cache, network);        queue.start();        return queue;    }

 假如Cache还要拓展一个功能,XCache。那么调用者不要修改代码,提供者也不要修改原有存在代码,只要添加实现Cache类即可。



  (3) 里氏替换(L)

            定义:子类必须能替换成父类

            原因:避免破坏继承结构

               里氏替换原则通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。它包含以下4层含义:

  • 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
  • 子类中可以增加自己特有的方法。
  • 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
  • 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

        看上去很不可思议,因为我们会发现在自己编程中常常会违反里氏替换原则,程序照样跑的好好的。所以大家都会产生这样的疑问,假如我非要不遵循里氏替换原则会有什么后果?

        后果就是:你写的代码出问题的几率将会大大增加。



   (4)接口隔离(I)
                      定义:客户端不要依赖他不需要的接口。接口细化

              原因:如果依赖过多不用的方法,会导致一些不可预知的改变


   (5) 依赖倒置:
           定义:高层模块不应直接依赖底层模块,而是依赖抽象模块。
           抽象不应依赖细节,细节必须依赖抽象
           原因:高层模块依赖底层模块:高层模块调用底层方法。
           高层模块依赖抽象:基于抽象层编程

           底层模块依赖抽象:继承或实现抽象层


          高层模块是业务复杂的模块,底层模块负责基本的原子操作。

     

public class RequestQueue {    /** Used for generating monotonically-increasing sequence numbers for requests. *///http://www.cnblogs.com/baizhanshi/p/5662376.html 原子操作,硬件保障private AtomicInteger mSequenceGenerator = new AtomicInteger();    /**     * Staging area for requests that already have a duplicate request in flight.     * 为什呢要给请求分段,是因为他在队列中有一个重复的请求     * <ul>     *     <li>containsKey(cacheKey) indicates that there is a request in flight for the given cache     *          key.</li>     *     <li>get(cacheKey) returns waiting requests for the given cache key. The in flight request     *          is <em>not</em> contained in that list. Is null if no requests are staged.</li>     * </ul>     */    private final Map<String, Queue<Request>> mWaitingRequests =            new HashMap<String, Queue<Request>>();    /**     * The set of all requests currently being processed by this RequestQueue. A Request     * will be in this set if it is waiting in any queue or currently being processed by     * any dispatcher.     */    private final Set<Request> mCurrentRequests = new HashSet<Request>();    /** The cache triage queue. */    private final PriorityBlockingQueue<Request> mCacheQueue =        new PriorityBlockingQueue<Request>();    /** The queue of requests that are actually going out to the network. */    private final PriorityBlockingQueue<Request> mNetworkQueue =        new PriorityBlockingQueue<Request>();    /** Number of network request dispatcher threads to start. */    private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4;    /** Cache interface for retrieving and storing respones. */    private final Cache mCache;    /** Network interface for performing requests. */    private final Network mNetwork;    /** Response delivery mechanism. */    private final ResponseDelivery mDelivery;    /** The network dispatchers. */    private NetworkDispatcher[] mDispatchers;    /** The cache dispatcher. */    private CacheDispatcher mCacheDispatcher;    /**     * Creates the worker pool. Processing will not begin until {@link #start()} is called.     *     * @param cache A Cache to use for persisting responses to disk     * @param network A Network interface for performing HTTP requests     * @param threadPoolSize Number of network dispatcher threads to create     * @param delivery A ResponseDelivery interface for posting responses and errors     * 传递响应和错误信息     */    public RequestQueue(Cache cache, Network network, int threadPoolSize,            ResponseDelivery delivery) {        mCache = cache;        mNetwork = network;        mDispatchers = new NetworkDispatcher[threadPoolSize];        mDelivery = delivery;    }

Cache.java

/** * An interface for a cache keyed by a String with a byte array as data. */public interface Cache {    /**     * Retrieves an entry from the cache.     * @param key Cache key     * @return An {@link Entry} or null in the event of a cache miss     */    public Entry get(String key);    /**     * Adds or replaces an entry to the cache.     * @param key Cache key     * @param entry Data to store and metadata for cache coherency, TTL, etc.     */    public void put(String key, Entry entry);    /**     * Performs any potentially long-running actions needed to initialize the cache;     * will be called from a worker thread.     */    public void initialize();    /**     * Invalidates an entry in the cache.     * @param key Cache key     * @param fullExpire True to fully expire the entry, false to soft expire     */    public void invalidate(String key, boolean fullExpire);    /**     * Removes an entry from the cache.     * @param key Cache key     */    public void remove(String key);    /**     * Empties the cache.     */    public void clear();    /**     * Data and metadata for an entry returned by the cache.     */    public static class Entry {        /** The data returned from cache. */        public byte[] data;        /** ETag for cache coherency. */        public String etag;        /** Date of this response as reported by the server. */        public long serverDate;        /** TTL for this record. */        public long ttl;        /** Soft TTL for this record. */        public long softTtl;        /** Immutable response headers as received from server; must be non-null. */        public Map<String, String> responseHeaders = Collections.emptyMap();        /** True if the entry is expired. */        public boolean isExpired() {            return this.ttl < System.currentTimeMillis();        }        /** True if a refresh is needed from the original data source. */        public boolean refreshNeeded() {            return this.softTtl < System.currentTimeMillis();        }    }}


Network.java

/** * An interface for performing requests. */public interface Network {    /**     * Performs the specified request.     * @param request Request to process     * @return A {@link NetworkResponse} with data and caching metadata; will never be null     * @throws VolleyError on errors     */    public NetworkResponse performRequest(Request<?> request) throws VolleyError;}


ResponseDelivery.java

public interface ResponseDelivery {    /**     * Parses a response from the network or cache and delivers it.     */    public void postResponse(Request<?> request, Response<?> response);    /**     * Parses a response from the network or cache and delivers it. The provided     * Runnable will be executed after delivery.     */    public void postResponse(Request<?> request, Response<?> response, Runnable runnable);    /**     * Posts an error for the given request.     */    public void postError(Request<?> request, VolleyError error);}



CacheDispatcher.java 缓存调度,高层模块不依赖细节,全是依赖抽象编程

public class CacheDispatcher extends Thread {    private static final boolean DEBUG = VolleyLog.DEBUG;    /** The queue of requests coming in for triage. */    private final BlockingQueue<Request> mCacheQueue;    /** The queue of requests going out to the network. */    private final BlockingQueue<Request> mNetworkQueue;    /** The cache to read from. */    private final Cache mCache;    /** For posting responses. */    private final ResponseDelivery mDelivery;    /** Used for telling us to die. */    private volatile boolean mQuit = false;    /**     * Creates a new cache triage dispatcher thread.  You must call {@link #start()}     * in order to begin processing.     *     * @param cacheQueue Queue of incoming requests for triage     * @param networkQueue Queue to post requests that require network to     * @param cache Cache interface to use for resolution     * @param delivery Delivery interface to use for posting responses     */    public CacheDispatcher(            BlockingQueue<Request> cacheQueue, BlockingQueue<Request> networkQueue,            Cache cache, ResponseDelivery delivery) {        mCacheQueue = cacheQueue;        mNetworkQueue = networkQueue;        mCache = cache;        mDelivery = delivery;    }    /**     * Forces this dispatcher to quit immediately.  If any requests are still in     * the queue, they are not guaranteed to be processed.     */    public void quit() {        mQuit = true;        interrupt();    }    @Override    public void run() {        if (DEBUG) VolleyLog.v("start new dispatcher");        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);//设置进程优先级        // Make a blocking call to initialize the cache.        //初始化缓存        mCache.initialize();        while (true) {            try {                // Get a request from the cache triage queue, blocking until                // at least one is available.            //从缓存队列中取一个可以用的                final Request request = mCacheQueue.take();                request.addMarker("cache-queue-take");                // If the request has been canceled, don't bother dispatching it.                //如果request已经被取消,不要打扰到传递                if (request.isCanceled()) {                    request.finish("cache-discard-canceled");                    continue;                }                // Attempt to retrieve this item from cache.                //取回缓存                Cache.Entry entry = mCache.get(request.getCacheKey());                if (entry == null) {                    request.addMarker("cache-miss");                    // Cache miss; send off to the network dispatcher.                    //缓存不存在,则加入到网络请求队列中                    mNetworkQueue.put(request);                    continue;                }                // If it is completely expired, just send it to the network.                //如果缓存过期了,则加入到网络请求队列中                if (entry.isExpired()) {                    request.addMarker("cache-hit-expired");                    request.setCacheEntry(entry);                    mNetworkQueue.put(request);                    continue;                }                // We have a cache hit; parse its data for delivery back to the request.                //我们找到了cache(不过期,没取消),解析数据传递到请求中区                request.addMarker("cache-hit");                Response<?> response = request.parseNetworkResponse(                        new NetworkResponse(entry.data, entry.responseHeaders));                request.addMarker("cache-hit-parsed");                if (!entry.refreshNeeded()) {                    // Completely unexpired cache hit. Just deliver the response.                //获取到没过期的缓存,传输这个响应                    mDelivery.postResponse(request, response);                } else {                    // Soft-expired cache hit. We can deliver the cached response,                    // but we need to also send the request to the network for                    // refreshing.                //缓存需要刷新                    request.addMarker("cache-hit-refresh-needed");                    request.setCacheEntry(entry);                    // Mark the response as intermediate.                    response.intermediate = true;                    // Post the intermediate response back to the user and have                    // the delivery then forward the request along to the network.                    //缓存过期之后,把请求放入到网络队列中去                    mDelivery.postResponse(request, response, new Runnable() {                        @Override                        public void run() {                            try {                            //加入到网络队列里面去                                mNetworkQueue.put(request);                            } catch (InterruptedException e) {                                // Not much we can do about this.                            }                        }                    });                }            } catch (InterruptedException e) {                // We may have been interrupted because it was time to quit.                if (mQuit) {                    return;                }                continue;            }        }    }}


都是依赖抽象


参考文章:

http://blog.csdn.net/zhengzhb/article/details/7281833

原创粉丝点击