Java design patterns

Java有不少種模式,如下的是一些總結的模式。java

(1) 單例模式 (實現方式 私有構造器 + 私有靜態自己的實例 + 共有實例方法返回自己的實例), 須要判斷是否已經生成過實例)一個類只容許其有一個實例化對象 在併發程序中用的可能比較多, 涉及線程安全, 我本身知道的是Spring 依賴注入, 在容器中的Bean通常都是單例的..
public class Singelton { // 最平凡的實現方式
private volatile static Singelton singelton;
public static Singelton getInstance(){
if(singelton == null) {
synchronized {
if(singelton == null) {
singelton = new Singelton();
return singelton;
}
}
}
}
}
單例模式的三種實現方式:
餓漢方式: 
對象類型聲明成static final 類型, 而且直接實例化 而後用getInstance()方法來獲取變量引用 這樣能夠保證對象惟一
懶漢方式:
對象類型聲明成 volatile static 類型
經過getInstance 的判斷 來實現對象惟一, 可是這個要考慮到併發問題, 多線程狀況下並不安全, 須要用雙重檢查機制, 而且把類型聲明稱volatile static
最好的方式(java語言 也就是由於jvm才特有的方法):
經過內部私有靜態類來實現單例, 在這個類內部實例化一個static final的實例
而後用一個方法調用這個靜態類的這個靜態實例 他的優勢就是結合了上頭兩種方式的全部優勢, 便可以懶加載, 也能夠保護線程安全,設計模式

(2)工廠模式(一個建立型設計模式) 有不少實現的例子 好比說不少帶有*BeanFactrory的類 都是工廠模式的體現 他經過形參等 生成不一樣的對象 LoggerFactory BeanFactory 等. 其實就是經過工廠的方式, 返回某個接口不一樣的實例, 其實就是能夠根據客戶要求的返回她想要的產品..
工廠模式分爲三種:
第一種: 簡單工廠(靜態工廠) 有一個工廠類擁有一個靜態的方法, 用來產生產品實例, 經過傳遞參數的不一樣來區分生成哪一個產品實例.
第二種: 工廠方法 : 這個是用來解決簡單工廠存在的問題 好比: 增長一個產品簡單工廠須要對工廠類代碼進行修改, 增長一個判斷條件, 這樣就增長了代碼的複雜程度, 工廠方法爲了解決這個問題, 經過多態的方式來實現不一樣的工廠類來生產不一樣的產品. 即會有一個工廠接口, 經過實現工廠接口的方式實現新的工廠類, 來代替修改工廠類代碼, 這樣會使得代碼耦合度下降. 
(更深一步, 工廠類甚至能夠加入產品的業務方法, 直接調用自己建立的產品的方法).
第三種: 抽象工廠 爲產品分類, 將縱向的產品實現類, 橫向化, 就是組成更大的產品工廠 具體實現如圖:(手畫工廠圖) 用來生產複雜的產品.
(3)觀察者模式 用於一對多 或者是 一對一 關係中 在一中有什麼改動 會致使和他有關係的多(也就是觀察者們也發生變更) 
Redis 實現異步消息隊列 有一種實現方式叫: 發佈訂閱者模式 相似可是 調度方式不同 觀察者模式由發佈者調度 而 另外一種模式不是 他有單獨的調度中心
例子:
public interface Subject {
public void attach(Observer o);
public void detach(Observer o);
public void notice();
}
interface Observer{
public void update();
}
class Student implements Observer{
String teacherPhone = "";
Teacher teacher ;
public Student(String phone,Teacher t){
teacher = t;
teacherPhone = phone;
}
@Override
public void update() {
teacherPhone = teacher.getPhone();
}
public void show(){
System.out.println(teacherPhone);
}
}
class Teacher implements Subject{
private String phone;
private ArrayList<Observer> students;
public Teacher(){
phone = "";
students = new ArrayList<Observer>();
}
@Override
public void attach(Observer o) {
students.add(o);
}
@Override
public void detach(Observer o) {
students.remove(o);
}
@Override
public void notice() {
for(Observer o:students){
o.update();
}
}
public String getPhone(){
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
notice();
}
}
Test:
public static void main(String[] args) {
Teacher teacher = new Teacher();
Student s = new Student("",teacher);
Student s1 = new Student("",teacher);
teacher.attach(s);
teacher.attach(s1);
teacher.setPhone("13215646");//核心在這個set方法上 他的變更致使不少都發生了改變
s.show();
s1.show();
}安全

(4) 外觀模式(門面模式) Facade Pattern
這個感受是最簡單的 他經過一個門面類 將具體操做隱藏在方法中 客戶只須要調用方法 不用知道具體的實現 這樣就很好
(說的個更加科學一點就是, 這個模式的做用就是實現客戶端和子系統的解耦, 用戶在調用客戶端接口的時候咱們能夠將它具體調用的操做隱藏起來, 只須要給他提供一個門面接口, 這樣就可使得調用更加簡單)
public void Solution(){
Analyze a = new Analyze();//這三個類的具體實現不知道 不過用戶只要對調用方法 自動都會產生結果
Think t = new Think();
Finally f = new Finally();
a.Analyze();
t.Think();
f.Finally();
}
public class Test {
public static void main(String[] args) {
Problem p = new Problem();
p.Solution();
}
}多線程

(5)組合模式 解釋一下這個模式是什麼, 首先他是用來解決樹形對象模型的(這個說的有一點不是很確切, 我感受組合模式是用來解決相似有多種不一樣的對象, 可是他們之間還有必定的類似性 相似於這種問題就能夠用組合模式來解決, 組合模式能夠將他們抽象到一個Component), 就是例如文件系統這種樹形的結構. 他的方式是經過將葉子節點(文件), 非葉子結點(文件夾) , 抽象成一個component類或者是接口, 而後葉子節點和非葉子結點, 分別實現一下這個類, 而後經過重寫方法的形式來實現樹形遍歷
還分爲兩種: 透明組合模式 安全組合模式併發

(6)命令模式
先上圖:(傳統的命令模式 可能都不是這麼用)
這個模式能夠類比於開關, 有不一樣的功能選項, 當你按不一樣的按鈕的時候, 會有不一樣的物品反應你的命令(暫時理解就是這個含義) 
對於上圖來講, 一個命令模式須要一個Invoker調用者, 也就是發出命令的人, 它關聯了一個command對象(或者是一系列command對象), 而後咱們須要具體的command實現類, 用來調用Handler(某個功能具體的實現類), 這個圖還少了個模塊就是咱們應該將Handler抽象成接口, 這樣的話, 若是添加刪除具體的Handler也能夠減小咱們修改以前的代碼. 而後咱們的邏輯關係是, 咱們的實現類接口會關聯一個Handler, 經過set方法set具體的Handler實現類以後, 調用具體的功能模塊.................(這是傳統的)異步

可是如今的命令名模式不少狀況下都不是直接將Handler和Command 耦合起來, 由於咱們要知足設計的高內聚弱耦合的原則, 因此 -> 演變出了一個命令隊列.jvm

 

(7)裝飾模式 (分爲透明裝飾模式和半透明裝飾模式) 
而後簡單的說一下這個模式是什麼, 這個模式是爲了爲被修飾的類添加一個方法, 其實就是裝飾一下一個類, 使其具備其餘功能, 具體的實現方式是: 首先咱們須要一個被裝飾的抽象構建Component(其有一個須要被修飾的方法), 而後咱們須要一個抽象裝飾器類Decorator, 實現咱們的須要被修飾的抽象構建, 而後與其關聯一下. 最後咱們須要一個具體的裝飾器類ConcreteDecorator, 它實現咱們的抽象裝飾器類, 而後加入咱們要加入的 方法, 這樣咱們就能夠爲咱們的具體實現類set一個ConcreteComponent, 以後就能夠調用被修飾的方法.jsp

(8)代理模式 這個模式較難 單獨創建了一個文檔 詳見 java學習/代理模式ide

(9)原型模式 這個模式就是獲取原型的一個克隆對象, 克隆對象和原型不能是同一個對象的引用. 在java中能夠調用基類Object 的clone() 方法, 可是要重寫這個方法必須實現Cloneable
這個模式有兩種級別: 
淺克隆 : 就是上頭說到的那種狀況, 實現一個Cloneable 接口 這個只能克隆基本類型, 可是對於引用類型 他只能克隆引用類型的地址 因此說引用類型的對象克隆以後兩個實例指向的仍是一個對象
深克隆 : 這個是經過實現一個Serializable 接口來實現 , 把對象實例放到流裏, 而後再取回來, 這樣就能夠得到一個新的克隆實例
(10)建造者模式
建造者模式相似於抽象工廠模式, 抽象工廠是將不一樣的產品進行組合, 組合成新產品, 他是用來生產複雜產品(也就是類)的. 相似的, 建造者模式是用來產生複雜對象的, 在這裏二者的核心區別就是, 建造者模式使用來生產複雜對象的, 他把一個對象的不一樣屬性的建造抽象化, 也就是說一個對象的屬性的值是經過調用建造函數獲取的, 相對的抽象工廠是用來說不一樣種的產品(也就是類) 組合起來生成新的產品的過程, 他的組裝對象是類. 而建造者模式組裝的是屬性函數

首先他分爲, 要生產的對象 Actor , 建造者(AbstrackBuilder, *Builder) , 控制者
抽象建造者有一個Actor類型的屬性, 而且有爲這個Actor 的各個屬性賦值的函數, 具體建造者繼承抽象建造者, 而後實現具體的建造函數, 最後控制者須要一個具體建造者做爲參數, 控制者分別調用具體建造者的建造函數, 而後獲取這個建造出來的Actor 也就是說我能夠選擇不調用某個函數, 這樣就很靈活

(11)適配器模式
這個模式的含義個人理解是, 咱們有一個(目標/目的)抽象類的兩個方法, 可是在某個地方已經有實現了的現成的方法, 那麼咱們想要不用本身再從新實現一遍這兩個同樣的方法有兩種辦法 1.把以前實現的代碼copy過去, 2. 就是寫一個目標抽象類的適配器, 
對於第二種方法也就是實現這個抽象類而後提供一下這兩個方法的實現, 而後這兩個方法的實現是經過關聯已經實現過這兩個方法的類而後調用他們的方法來實現, 這樣就避免了copy代碼從而增長代碼長度, 並且冗餘度高的問題.

而後適配器模式還分爲對象適配器模式和類適配器模式, 對象適配器模式是經過關聯的方式來調用適配者的方法, 可是類適配器模式是經過繼承的方式, 因爲java語言單繼承的特性, 其實這個類適配器模式不多被使用, 
適配器模式有一種雙向適配器模式, 這個其實就是能夠雙向適配. 適配者是雙方的.還有一種叫缺省適配器, 缺省適配器的最大的特色就是適配器類是一個抽象的, 他不用實現目標接口的全部方法, 而是能夠只實現幾個.

(12)橋接模式
廢話很少說先來上個圖
來解釋一下這個橋接模式, 首先他的做用是分離一個實體中兩種或者多種維度的抽象, 把他們抽象成抽象類 -> 關聯 -> 抽象接口的模式 這樣就能夠了 要增添新的類型, 只須要在他對應的維度下建立一個對應的具體實現類, 而後就能夠實現複雜功能的解耦.

(13) 享元模式 (不是特別經常使用)
這個模式的做用就是, 實現一個享元工廠, 將一些具備相同功能的對象集中起來, 減小對象的數量, 下降系統由於對象冗餘致使的內存消耗, 最典型的例子運用了享元模式的就是String這個對象. 每次建立新對象的時候他老是要先在常量池中查找是否是已經有了相同字符串的引用若是有了的話就不用在建立一個新的對象了, 只要把以前那個字符串的引用返回便可

(14)職責鏈模式
責任鏈模式是什麼尼? 其實責任鏈模式就是對於一系列的處理, 請求須要在一個鏈上依次傳遞. (相似於jsp的過濾器和Spring的攔截器) 
責任鏈模式分爲純的責任鏈模式和不純的責任鏈模式. 
純的責任鏈就是責任鏈的每個handler只能選擇兩種處理1: 處理請求 2: 傳給下一個
不純的責任鏈其實就是handler在處理完以後能夠再傳給下一家。

固然,還有其餘的模式,就不一一闡述了。僅供參考。

相關文章
相關標籤/搜索