設計模式筆記

工廠模式

解釋: (這種說法存在疑問: 由於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代理

代理模式(spring實現AOP的主要方法)

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();

這段代碼有代碼的入侵, 能夠考慮使用動態代理來減小代碼的侵入, 下降
耦合度;

以上內容只是一個大概的目錄, 後續會繼續修改;

相關文章
相關標籤/搜索