解釋: (這種說法存在疑問: 由於abs抽象類能夠直接去掉, 等到後面看spring源碼的時候在說), 快速建立同一個類的不一樣的實現的, 並隱藏該類的建立過程, 直接獲取, 隨着類的愈來愈多, 分類的愈來愈複雜, 工廠開始專業化, 所以出現了工廠的分類, 所以出現了工廠的分類, 抽象工廠模式java
abstractFactory { getA() getB() getC() }
factory extends abstractFactory { getA(){...} getB(){...} getC(){...} }
這裏使用抽象類的主要緣由是, 抽象類中能夠實現一些公共的邏輯, 又
能夠添加繼承類必需要實現的方法, 這種模式是在spring中使用的最多的;web
主要是保證在項目中只有一個實例, 保證線程的安全, 同時系統節省開銷.spring
餓漢式
不論用不用都先new出來, 這種的能夠保證線程安全, 可是增長系統開銷
可是使用序列化和反序列化的時候, 仍是能夠獲取到兩個實例, 能夠在類中添加安全
readResolve() { return a; }
方法來避免;併發
class A { private A () {} private static final A a = new A() public static A getInstance() { return a; } }
懶漢式
用的時候在new, 會存在線程安全問題, 和指令重排序問題ide
class A { private V () {} private static final A a = null public static A getInstance() { if(a == null) { return new A(); } return a; } }
解決的方法:
a). 使用double check+volatile
b). 或者使用靜態內部類: 主要是由於靜態內部類不論外部類被加載
多少次, 他只加載一次(可使用反射來屢次獲取)spa
class A { private V () {} public static A getInstance() { return B.a } private static class B { private static final A a = new A() } }
註冊式單例
將對象向同一個容器中註冊, 下次使用時直接從容器中獲取, spring中使用的就是註冊式單例, 須要使用currentHashMap();線程
深複製和淺複製問題
深複製可使用字節碼來實現, readObject代理
a). 普通的代理模式(缺點, 只能幫有限的對象進行代理, 存在侷限性)code
class son { findLove() }
class proxy { proxy() { son傳入 } findLove() { ... son.findLove ... } }
b). jdk的動態代理
class son implement Person{ findLove() }
class Proxy implement InvocationHandler { Proxy () { 傳入對象son } invoke(...) { ... method.invoke(son, args) ... } }
使用方法
Son son = new Son() Proxy proxy = new Proxy(son) Person person = (Person)Proxy.newProxyInstance(son.getClass.getClassLoader,son.getClass.getInterfaces,proxy) person.findLove()
實現的原理
就是使用從新生成類的字節碼方法, 獲取到被代理類的引用, 而後使用代理類, 從新生成字節碼, 並在字節碼中加入要實現的方法;
c). cjlib代理方法
public class Dao { public void update() { System.out.println("PeopleDao.update()"); } public void select() { System.out.println("PeopleDao.select()"); } }
public class DaoProxy implements MethodInterceptor { @Override public Object intercept(Object object, Method method, Object\[\] objects, MethodProxy proxy) throws Throwable { System.out.println("Before Method Invoke"); proxy.invokeSuper(object, objects); System.out.println("After Method Invoke"); return object; } }
使用方法
DaoProxy daoProxy = new DaoProxy(); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Dao.class); enhancer.setCallback(daoProxy); Dao dao = (Dao)enhancer.create(); dao.update(); dao.select();
委派模式 : 是靜態代理的一種特殊狀況, Delegate和dispacher開頭的是委派模式
實現方式
class ServletDispacher { //list中保存了須要被委派的對象 ArrayList<Handler> handlers = new ArrayList<>(); doDispacher () { //該方法中, 進行相關的邏輯判斷, 來選擇要讓哪一個Handler來去執行這個任務 } class Handler { ... } }
java Web中的Servlet就是使用的這種模式來接受請求, 併發送給對應的controller去執行的相關請求;
能夠想象成一種電源轉化器, 主要是在不改變原有功能的基礎上, 對當下的業務作兼容,實現的方法
class Login { login(){} }
class ThirdLogin extends Login{ webLogin () { //處理相關邏輯 super.login() } qqLogin () { //處理相關邏輯 super.login() } }
裝飾者模式
和適配器模式優勢相似, 裝飾者模式應用最典型的是java的inputStream和outputStream,而和適配器模式根本區別就是, 不論新對象如何裝飾, 他們的頂層都是實現了InputStream的接口, 並且在實現的時候, 能夠覆蓋原來的方法, 是方法功能更強大, 能夠將裝飾者模者模式理解成特別的適配器模式;
觀察者模式
顧名思義: 就是一個觀察者, 在監聽一個主題, 當這個主題發生改變或者發出消息時, 將消息發送給已經訂閱該主題的訂閱者
class Subject { List observer ...; add(){} remove(){} advice() { //遍歷observer //而後observer.update() } }
//具體的主題
class ConcreteSubject { dosomeThing () { ... super.advice() {} } }
interface Observer { update() }
具體的觀察者
class ConcreteObserver implement Observer{ uodate () { ... } }
使用方法
Observer observer = new ConcreteObserver() Subject subject = new ConcreteSubject() subject.add(observer) subject.dosomeThing();
這段代碼有代碼的入侵, 能夠考慮使用動態代理來減小代碼的侵入, 下降
耦合度;
以上內容只是一個大概的目錄, 後續會繼續修改;