您的位置:首页 > 其它

面向对象-设计原则

2017-07-31 10:57 239 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息