參考地址:http://c.biancheng.net/view/1317.html
1.分類
1.按目的分類
1.創(chuàng)建型模式:用于描述“怎樣創(chuàng)建對象”,它的主要特點是“將對象的創(chuàng)建與使用分離”锣夹。GoF 中提供了單例啤誊、原型淹禾、工廠方法雪标、抽象工廠筷狼、建造者等 5 種創(chuàng)建型模式动看。
2.結(jié)構(gòu)型模式:用于描述如何將類或?qū)ο蟀茨撤N布局組成更大的結(jié)構(gòu)裕偿,GoF 中提供了代理洞慎、適配器、橋接嘿棘、裝飾劲腿、外觀、享元鸟妙、組合等 7 種結(jié)構(gòu)型模式焦人。
3.行為型模式:用于描述類或?qū)ο笾g怎樣相互協(xié)作共同完成單個對象都無法單獨完成的任務挥吵,以及怎樣分配職責。GoF 中提供了模板方法花椭、策略忽匈、命令、職責鏈矿辽、狀態(tài)丹允、觀察者、中介者袋倔、迭代器雕蔽、訪問者、備忘錄奕污、解釋器等 11 種行為型模式萎羔。
2.根據(jù)作用范圍
1.類模式:用于處理類與子類之間的關(guān)系,這些關(guān)系通過繼承來建立碳默,是靜態(tài)的,在編譯時刻便確定下來了缘眶。GoF中的工廠方法嘱根、(類)適配器、模板方法巷懈、解釋器屬于該模式该抒。
2.對象模式:用于處理對象之間的關(guān)系,這些關(guān)系可以通過組合或聚合來實現(xiàn)顶燕,在運行時刻是可以變化的凑保,更具動態(tài)性。GoF 中除了以上 4 種涌攻,其他的都是對象模式欧引。
2.設(shè)計模式各種功能
1.單例(Singleton)模式:某個類只能生成一個實例,該類提供了一個全局訪問點供外部獲取該實例恳谎,其拓展是有限多例模式芝此。
2.原型(Prototype)模式:將一個對象作為原型,通過對其進行復制而克隆出多個和原型類似的新實例因痛。
3.工廠方法(Factory Method)模式:定義一個用于創(chuàng)建產(chǎn)品的接口婚苹,由子類決定生產(chǎn)什么產(chǎn)品。
4.抽象工廠(AbstractFactory)模式:提供一個創(chuàng)建產(chǎn)品族的接口鸵膏,其每個子類可以生產(chǎn)一系列相關(guān)的產(chǎn)品膊升。
5.建造者(Builder)模式:將一個復雜對象分解成多個相對簡單的部分,然后根據(jù)不同需要分別創(chuàng)建它們谭企,最后構(gòu)建成該復雜對象廓译。
6.代理(Proxy)模式:為某對象提供一種代理以控制對該對象的訪問评肆。即客戶端通過代理間接地訪問該對象,從而限制责循、增強或修改該對象的一些特性糟港。
7.適配器(Adapter)模式:將一個類的接口轉(zhuǎn)換成客戶希望的另外一個接口,使得原本由于接口不兼容而不能一起工作的那些類能一起工作院仿。
8.橋接(Bridge)模式:將抽象與實現(xiàn)分離秸抚,使它們可以獨立變化。它是用組合關(guān)系代替繼承關(guān)系來實現(xiàn)歹垫,從而降低了抽象和實現(xiàn)這兩個可變維度的耦合度剥汤。
9.裝飾(Decorator)模式:動態(tài)的給對象增加一些職責,即增加其額外的功能排惨。
10.外觀(Facade)模式:為多個復雜的子系統(tǒng)提供一個一致的接口吭敢,使這些子系統(tǒng)更加容易被訪問。
11.享元(Flyweight)模式:運用共享技術(shù)來有效地支持大量細粒度對象的復用暮芭。
12.組合(Composite)模式:將對象組合成樹狀層次結(jié)構(gòu)鹿驼,使用戶對單個對象和組合對象具有一致的訪問性。
13.模板方法(TemplateMethod)模式:定義一個操作中的算法骨架辕宏,而將算法的一些步驟延遲到子類中畜晰,使得子類可以不改變該算法結(jié)構(gòu)的情況下重定義該算法的某些特定步驟。
14.策略(Strategy)模式:定義了一系列算法瑞筐,并將每個算法封裝起來凄鼻,使它們可以相互替換,且算法的改變不會影響使用算法的客戶聚假。
15.命令(Command)模式:將一個請求封裝為一個對象块蚌,使發(fā)出請求的責任和執(zhí)行請求的責任分割開。
16.職責鏈(Chain of Responsibility)模式:把請求從鏈中的一個對象傳到下一個對象膘格,直到請求被響應為止峭范。通過這種方式去除對象之間的耦合。
17.狀態(tài)(State)模式:允許一個對象在其內(nèi)部狀態(tài)發(fā)生改變時改變其行為能力闯袒。
18.觀察者(Observer)模式:多個對象間存在一對多關(guān)系虎敦,當一個對象發(fā)生改變時,把這種改變通知給其他多個對象政敢,從而影響其他對象的行為其徙。
19.中介者(Mediator)模式:定義一個中介對象來簡化原有對象之間的交互關(guān)系,降低系統(tǒng)中對象間的耦合度喷户,使原有對象之間不必相互了解唾那。
20.迭代器(Iterator)模式:提供一種方法來順序訪問聚合對象中的一系列數(shù)據(jù),而不暴露聚合對象的內(nèi)部表示。
21.訪問者(Visitor)模式:在不改變集合元素的前提下闹获,為一個集合中的每個元素提供多種訪問方式期犬,即每個元素有多個訪問者對象訪問。
22.備忘錄(Memento)模式:在不破壞封裝性的前提下避诽,獲取并保存一個對象的內(nèi)部狀態(tài)龟虎,以便以后恢復它。
23.解釋器(Interpreter)模式:提供如何定義語言的文法沙庐,以及對語言句子的解釋方法鲤妥,即解釋器。
3.具體設(shè)計模式
------創(chuàng)建型模式-------
1.單例模式
1.定義與特點
單例(Singleton)模式的定義:指一個類只有一個實例拱雏,且該類能自行創(chuàng)建這個實例的一種模式棉安。例如,Windows 中只能打開一個任務管理器铸抑,這樣可以避免因打開多個任務管理器窗口而造成內(nèi)存資源的浪費贡耽,或出現(xiàn)各個窗口顯示內(nèi)容的不一致等錯誤。
單例模式有 3 個特點:
1.單例類只有一個實例對象鹊汛;
2.該單例對象必須由單例類自行創(chuàng)建蒲赂;
3.單例類對外提供一個訪問該單例的全局訪問點;
2.模式的實現(xiàn)
懶漢式
public class LazySingleton
{
private static volatile LazySingleton instance=null; //保證 instance 在所有線程中同步
private LazySingleton(){} //private 避免類在外部被實例化
public static synchronized LazySingleton getInstance()
{
//getInstance 方法前加同步
if(instance==null)
{
instance=new LazySingleton();
}
return instance;
}
}
餓漢式
public class HungrySingleton
{
private static final HungrySingleton instance=new HungrySingleton();
private HungrySingleton(){}
public static HungrySingleton getInstance()
{
return instance;
}
}
3.應用場景
1.在應用場景中刁憋,某類只要求生成一個對象的時候凳宙,如一個班中的班長、每個人的身份證號等职祷。
2.當對象需要被共享的場合。由于單例模式只允許創(chuàng)建一個對象届囚,共享該對象可以節(jié)省內(nèi)存有梆,并加快對象訪問速度。如 Web 中的配置對象意系、數(shù)據(jù)庫的連接池等泥耀。
3.當某類需要頻繁實例化,而創(chuàng)建的對象又頻繁被銷毀的時候蛔添,如多線程的線程池痰催、網(wǎng)絡(luò)連接池等。
2.原型模式
1.定義與特點
用一個已經(jīng)創(chuàng)建的實例作為原型迎瞧,通過復制該原型對象來創(chuàng)建一個和原型相同或相似的新對象夸溶。在這里,原型實例指定了要創(chuàng)建的對象的種類凶硅。用這種方式創(chuàng)建對象非常高效缝裁,根本無須知道對象創(chuàng)建的細節(jié)。
1.抽象原型類:規(guī)定了具體原型對象必須實現(xiàn)的接口足绅。
2.具體原型類:實現(xiàn)抽象原型類的 clone() 方法捷绑,它是可被復制的對象韩脑。
3.訪問類:使用具體原型類中的 clone() 方法來復制新的對象。
2.模式的實現(xiàn)
public class ProtoTypeCitation
{
public static void main(String[] args) throws CloneNotSupportedException
{
citation obj1=new citation("張三","同學:在2016學年第一學期中表現(xiàn)優(yōu)秀粹污,被評為三好學生段多。","韶關(guān)學院");
obj1.display();
citation obj2=(citation) obj1.clone();
obj2.setName("李四");
obj2.display();
}
}
//獎狀類
class citation implements Cloneable
{
String name;
String info;
String college;
citation(String name,String info,String college)
{
this.name=name;
this.info=info;
this.college=college;
System.out.println("獎狀創(chuàng)建成功!");
}
void setName(String name)
{
this.name=name;
}
String getName()
{
return(this.name);
}
void display()
{
System.out.println(name+info+college);
}
public Object clone() throws CloneNotSupportedException
{
System.out.println("獎狀拷貝成功壮吩!");
return (citation)super.clone();
}
}
3.應用場景
1.對象之間相同或相似进苍,即只是個別的幾個屬性不同的時候。
2.對象的創(chuàng)建過程比較麻煩粥航,但復制比較簡單的時候琅捏。
3.工廠模式
1.定義與特點
定義一個創(chuàng)建產(chǎn)品對象的工廠接口,將產(chǎn)品對象的實際創(chuàng)建工作推遲到具體子工廠類當中递雀。這滿足創(chuàng)建型模式中所要求的“創(chuàng)建與使用相分離”的特點柄延。
1.用戶只需要知道具體工廠的名稱就可得到所要的產(chǎn)品,無須知道產(chǎn)品的具體創(chuàng)建過程缀程;
2.在系統(tǒng)增加新的產(chǎn)品時只需要添加具體產(chǎn)品類和對應的具體工廠類搜吧,無須對原工廠進行任何修改,滿足開閉原則杨凑;
其缺點是:每增加一個產(chǎn)品就要增加一個具體產(chǎn)品類和一個對應的具體工廠類滤奈,這增加了系統(tǒng)的復雜度。
2.模式的實現(xiàn)
package FactoryMethod;
public class AbstractFactoryTest
{
public static void main(String[] args)
{
try
{
Product a;
AbstractFactory af;
af=(AbstractFactory) ReadXML1.getObject();
a=af.newProduct();
a.show();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
//抽象產(chǎn)品:提供了產(chǎn)品的接口
interface Product
{
public void show();
}
//具體產(chǎn)品1:實現(xiàn)抽象產(chǎn)品中的抽象方法
class ConcreteProduct1 implements Product
{
public void show()
{
System.out.println("具體產(chǎn)品1顯示...");
}
}
//具體產(chǎn)品2:實現(xiàn)抽象產(chǎn)品中的抽象方法
class ConcreteProduct2 implements Product
{
public void show()
{
System.out.println("具體產(chǎn)品2顯示...");
}
}
//抽象工廠:提供了廠品的生成方法
interface AbstractFactory
{
public Product newProduct();
}
//具體工廠1:實現(xiàn)了廠品的生成方法
class ConcreteFactory1 implements AbstractFactory
{
public Product newProduct()
{
System.out.println("具體工廠1生成-->具體產(chǎn)品1...");
return new ConcreteProduct1();
}
}
//具體工廠2:實現(xiàn)了廠品的生成方法
class ConcreteFactory2 implements AbstractFactory
{
public Product newProduct()
{
System.out.println("具體工廠2生成-->具體產(chǎn)品2...");
return new ConcreteProduct2();
}
}
3.應用場景
1.客戶只知道創(chuàng)建產(chǎn)品的工廠名撩满,而不知道具體的產(chǎn)品名蜒程。如 TCL 電視工廠、海信電視工廠等伺帘。
2.創(chuàng)建對象的任務由多個具體子工廠中的某一個完成昭躺,而抽象工廠只提供創(chuàng)建產(chǎn)品的接口。
3.客戶不關(guān)心創(chuàng)建產(chǎn)品的細節(jié)伪嫁,只關(guān)心產(chǎn)品的品牌领炫。
4.抽象工廠模式
1.定義與特點
是一種為訪問類提供一個創(chuàng)建一組相關(guān)或相互依賴對象的接口,且訪問類無須指定所要產(chǎn)品的具體類就能得到同族的不同等級的產(chǎn)品的模式結(jié)構(gòu)张咳。
抽象工廠模式是工廠方法模式的升級版本帝洪,工廠方法模式只生產(chǎn)一個等級的產(chǎn)品,而抽象工廠模式可生產(chǎn)多個等級的產(chǎn)品脚猾。
1.可以在類的內(nèi)部對產(chǎn)品族中相關(guān)聯(lián)的多等級產(chǎn)品共同管理葱峡,而不必專門引入多個新的類來進行管理。
2.當增加一個新的產(chǎn)品族時不需要修改原代碼婚陪,滿足開閉原則族沃。
2.模式的實現(xiàn)
package AbstractFactory;
import java.awt.*;
import javax.swing.*;
public class FarmTest
{
public static void main(String[] args)
{
try
{
Farm f;
Animal a;
Plant p;
f=(Farm) ReadXML.getObject();
a=f.newAnimal();
p=f.newPlant();
a.show();
p.show();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
//抽象產(chǎn)品:動物類
interface Animal
{
public void show();
}
//具體產(chǎn)品:馬類
class Horse implements Animal
{
JScrollPane sp;
JFrame jf=new JFrame("抽象工廠模式測試");
public Horse()
{
Container contentPane=jf.getContentPane();
JPanel p1=new JPanel();
p1.setLayout(new GridLayout(1,1));
p1.setBorder(BorderFactory.createTitledBorder("動物:馬"));
sp=new JScrollPane(p1);
contentPane.add(sp, BorderLayout.CENTER);
JLabel l1=new JLabel(new ImageIcon("src/A_Horse.jpg"));
p1.add(l1);
jf.pack();
jf.setVisible(false);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用戶點擊窗口關(guān)閉
}
public void show()
{
jf.setVisible(true);
}
}
//具體產(chǎn)品:牛類
class Cattle implements Animal
{
JScrollPane sp;
JFrame jf=new JFrame("抽象工廠模式測試");
public Cattle() {
Container contentPane=jf.getContentPane();
JPanel p1=new JPanel();
p1.setLayout(new GridLayout(1,1));
p1.setBorder(BorderFactory.createTitledBorder("動物:牛"));
sp=new JScrollPane(p1);
contentPane.add(sp, BorderLayout.CENTER);
JLabel l1=new JLabel(new ImageIcon("src/A_Cattle.jpg"));
p1.add(l1);
jf.pack();
jf.setVisible(false);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用戶點擊窗口關(guān)閉
}
public void show()
{
jf.setVisible(true);
}
}
//抽象產(chǎn)品:植物類
interface Plant
{
public void show();
}
//具體產(chǎn)品:水果類
class Fruitage implements Plant
{
JScrollPane sp;
JFrame jf=new JFrame("抽象工廠模式測試");
public Fruitage()
{
Container contentPane=jf.getContentPane();
JPanel p1=new JPanel();
p1.setLayout(new GridLayout(1,1));
p1.setBorder(BorderFactory.createTitledBorder("植物:水果"));
sp=new JScrollPane(p1);
contentPane.add(sp, BorderLayout.CENTER);
JLabel l1=new JLabel(new ImageIcon("src/P_Fruitage.jpg"));
p1.add(l1);
jf.pack();
jf.setVisible(false);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用戶點擊窗口關(guān)閉
}
public void show()
{
jf.setVisible(true);
}
}
//具體產(chǎn)品:蔬菜類
class Vegetables implements Plant
{
JScrollPane sp;
JFrame jf=new JFrame("抽象工廠模式測試");
public Vegetables()
{
Container contentPane=jf.getContentPane();
JPanel p1=new JPanel();
p1.setLayout(new GridLayout(1,1));
p1.setBorder(BorderFactory.createTitledBorder("植物:蔬菜"));
sp=new JScrollPane(p1);
contentPane.add(sp, BorderLayout.CENTER);
JLabel l1=new JLabel(new ImageIcon("src/P_Vegetables.jpg"));
p1.add(l1);
jf.pack();
jf.setVisible(false);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用戶點擊窗口關(guān)閉
}
public void show()
{
jf.setVisible(true);
}
}
//抽象工廠:農(nóng)場類
interface Farm
{
public Animal newAnimal();
public Plant newPlant();
}
//具體工廠:韶關(guān)農(nóng)場類
class SGfarm implements Farm
{
public Animal newAnimal()
{
System.out.println("新牛出生!");
return new Cattle();
}
public Plant newPlant()
{
System.out.println("蔬菜長成!");
return new Vegetables();
}
}
//具體工廠:上饒農(nóng)場類
class SRfarm implements Farm
{
public Animal newAnimal()
{
System.out.println("新馬出生脆淹!");
return new Horse();
}
public Plant newPlant()
{
System.out.println("水果長成常空!");
return new Fruitage();
}
}
3.應用場景
1.當需要創(chuàng)建的對象是一系列相互關(guān)聯(lián)或相互依賴的產(chǎn)品族時,如電器工廠中的電視機盖溺、洗衣機漓糙、空調(diào)等。
2.系統(tǒng)中有多個產(chǎn)品族烘嘱,但每次只使用其中的某一族產(chǎn)品昆禽。如有人只喜歡穿某一個品牌的衣服和鞋。
3.系統(tǒng)中提供了產(chǎn)品的類庫蝇庭,且所有產(chǎn)品的接口相同醉鳖,客戶端不依賴產(chǎn)品實例的創(chuàng)建細節(jié)和內(nèi)部結(jié)構(gòu)。
5.建造者模式
1.定義與特點
指將一個復雜對象的構(gòu)造與它的表示分離哮内,使同樣的構(gòu)建過程可以創(chuàng)建不同的表示盗棵,這樣的設(shè)計模式被稱為建造者模式。它是將一個復雜的對象分解為多個簡單的對象北发,然后一步一步構(gòu)建而成纹因。它將變與不變相分離,即產(chǎn)品的組成部分是不變的琳拨,但每一部分是可以靈活選擇的瞭恰。
1.各個具體的建造者相互獨立,有利于系統(tǒng)的擴展狱庇。
2.客戶端不必知道產(chǎn)品內(nèi)部組成的細節(jié)惊畏,便于控制細節(jié)風險。
2.模式的實現(xiàn)
產(chǎn)品角色:包含多個組成部件的復雜對象密任。
class Product
{
private String partA;
private String partB;
private String partC;
public void setPartA(String partA)
{
this.partA=partA;
}
public void setPartB(String partB)
{
this.partB=partB;
}
public void setPartC(String partC)
{
this.partC=partC;
}
public void show()
{
//顯示產(chǎn)品的特性
}
}
抽象建造者:包含創(chuàng)建產(chǎn)品各個子部件的抽象方法
abstract class Builder
{
//創(chuàng)建產(chǎn)品對象
protected Product product=new Product();
public abstract void buildPartA();
public abstract void buildPartB();
public abstract void buildPartC();
//返回產(chǎn)品對象
public Product getResult()
{
return product;
}
}
具體建造者:實現(xiàn)了抽象建造者接口陕截。
public class ConcreteBuilder extends Builder
{
public void buildPartA()
{
product.setPartA("建造 PartA");
}
public void buildPartB()
{
product.setPartA("建造 PartB");
}
public void buildPartC()
{
product.setPartA("建造 PartC");
}
}
指揮者:調(diào)用建造者中的方法完成復雜對象的創(chuàng)建。
class Director
{
private Builder builder;
public Director(Builder builder)
{
this.builder=builder;
}
//產(chǎn)品構(gòu)建與組裝方法
public Product construct()
{
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
return builder.getResult();
}
}
客戶類批什。
public class Client
{
public static void main(String[] args)
{
Builder builder=new ConcreteBuilder();
Director director=new Director(builder);
Product product=director.construct();
product.show();
}
}
3.應用場景
建造者(Builder)模式創(chuàng)建的是復雜對象,其產(chǎn)品的各個部分經(jīng)常面臨著劇烈的變化社搅,但將它們組合在一起的算法卻相對穩(wěn)定驻债,所以它通常在以下場合使用。
1.創(chuàng)建的對象較復雜形葬,由多個部件構(gòu)成合呐,各部件面臨著復雜的變化,但構(gòu)件間的建造順序是穩(wěn)定的笙以。
2.創(chuàng)建復雜對象的算法獨立于該對象的組成部分以及它們的裝配方式淌实,即產(chǎn)品的構(gòu)建過程和最終的表示是獨立的。
------結(jié)構(gòu)型模式-------
1.代理模式
1.定義與特點
代理模式的定義:由于某些原因需要給某對象提供一個代理以控制對該對象的訪問。這時拆祈,訪問對象不適合或者不能直接引用目標對象恨闪,代理對象作為訪問對象和目標對象之間的中介。
代理模式的主要優(yōu)點有:
1.代理模式在客戶端與目標對象之間起到一個中介作用和保護目標對象的作用放坏;
2.代理對象可以擴展目標對象的功能咙咽;
3.代理模式能將客戶端與目標對象分離,在一定程度上降低了系統(tǒng)的耦合度淤年;
其主要缺點是:
1.在客戶端和目標對象之間增加一個代理對象钧敞,會造成請求處理速度變慢;
2.增加了系統(tǒng)的復雜度麸粮;
2.模式的實現(xiàn)
package proxy;
public class ProxyTest
{
public static void main(String[] args)
{
Proxy proxy=new Proxy();
proxy.Request();
}
}
//抽象主題
interface Subject
{
void Request();
}
//真實主題
class RealSubject implements Subject
{
public void Request()
{
System.out.println("訪問真實主題方法...");
}
}
//代理
class Proxy implements Subject
{
private RealSubject realSubject;
public void Request()
{
if (realSubject==null)
{
realSubject=new RealSubject();
}
preRequest();
realSubject.Request();
postRequest();
}
public void preRequest()
{
System.out.println("訪問真實主題之前的預處理溉苛。");
}
public void postRequest()
{
System.out.println("訪問真實主題之后的后續(xù)處理。");
}
}
3.應用場景
1.遠程代理弄诲,這種方式通常是為了隱藏目標對象存在于不同地址空間的事實愚战,方便客戶端訪問。例如威根,用戶申請某些網(wǎng)盤空間時凤巨,會在用戶的文件系統(tǒng)中建立一個虛擬的硬盤,用戶訪問虛擬硬盤時實際訪問的是網(wǎng)盤空間洛搀。
2.虛擬代理敢茁,這種方式通常用于要創(chuàng)建的目標對象開銷很大時。例如留美,下載一幅很大的圖像需要很長時間彰檬,因某種計算比較復雜而短時間無法完成,這時可以先用小比例的虛擬代理替換真實的對象谎砾,消除用戶對服務器慢的感覺逢倍。
3.安全代理,這種方式通常用于控制不同種類客戶對真實對象的訪問權(quán)限景图。
4.智能指引较雕,主要用于調(diào)用目標對象時,代理附加一些額外的處理功能挚币。例如亮蒋,增加計算真實對象的引用次數(shù)的功能,這樣當該對象沒有被引用時妆毕,就可以自動釋放它慎玖。
- 延遲加載,指為了提高系統(tǒng)的性能笛粘,延遲對目標的加載趁怔。例如湿硝,[Hibernate] 中就存在屬性的延遲加載和關(guān)聯(lián)表的延時加載。
2.裝飾模式
1.定義與特點
裝飾(Decorator)模式的定義:指在不改變現(xiàn)有對象結(jié)構(gòu)的情況下润努,動態(tài)地給該對象增加一些職責(即增加其額外功能)的模式关斜,它屬于對象結(jié)構(gòu)型模式。
裝飾(Decorator)模式的主要優(yōu)點有:
1.采用裝飾模式擴展對象的功能比采用繼承方式更加靈活任连。
2.可以設(shè)計出多個不同的具體裝飾類蚤吹,創(chuàng)造出多個不同行為的組合。
其主要缺點是:裝飾模式增加了許多子類随抠,如果過度使用會使程序變得很復雜裁着。
2.模式的實現(xiàn)
package decorator;
public class DecoratorPattern
{
public static void main(String[] args)
{
Component p=new ConcreteComponent();
p.operation();
System.out.println("---------------------------------");
Component d=new ConcreteDecorator(p);
d.operation();
}
}
//抽象構(gòu)件角色
interface Component
{
public void operation();
}
//具體構(gòu)件角色
class ConcreteComponent implements Component
{
public ConcreteComponent()
{
System.out.println("創(chuàng)建具體構(gòu)件角色");
}
public void operation()
{
System.out.println("調(diào)用具體構(gòu)件角色的方法operation()");
}
}
//抽象裝飾角色
class Decorator implements Component
{
private Component component;
public Decorator(Component component)
{
this.component=component;
}
public void operation()
{
component.operation();
}
}
//具體裝飾角色
class ConcreteDecorator extends Decorator
{
public ConcreteDecorator(Component component)
{
super(component);
}
public void operation()
{
super.operation();
addedFunction();
}
public void addedFunction()
{
System.out.println("為具體構(gòu)件角色增加額外的功能addedFunction()");
}
}
3.應用場景
1.當需要給一個現(xiàn)有類添加附加職責,而又不能采用生成子類的方法進行擴充時拱她。例如二驰,該類被隱藏或者該類是終極類或者采用繼承方式會產(chǎn)生大量的子類。
2.當需要通過對現(xiàn)有的一組基本功能進行排列組合而產(chǎn)生非常多的功能時秉沼,采用繼承關(guān)系很難實現(xiàn)桶雀,而采用裝飾模式卻很好實現(xiàn)。
3.當對象的功能要求可以動態(tài)地添加唬复,也可以再動態(tài)地撤銷時矗积。
3.外觀模式
1.定義與特點
外觀(Facade)模式的定義:是一種通過為多個復雜的子系統(tǒng)提供一個一致的接口,而使這些子系統(tǒng)更加容易被訪問的模式敞咧。該模式對外有一個統(tǒng)一接口棘捣,外部應用程序不用關(guān)心內(nèi)部子系統(tǒng)的具體的細節(jié),這樣會大大降低應用程序的復雜度休建,提高了程序的可維護性乍恐。
外觀(Facade)模式是“迪米特法則”的典型應用,它有以下主要優(yōu)點测砂。
1.降低了子系統(tǒng)與客戶端之間的耦合度茵烈,使得子系統(tǒng)的變化不會影響調(diào)用它的客戶類。
2.對客戶屏蔽了子系統(tǒng)組件砌些,減少了客戶處理的對象數(shù)目呜投,并使得子系統(tǒng)使用起來更加容易。
3.降低了大型軟件系統(tǒng)中的編譯依賴性存璃,簡化了系統(tǒng)在不同平臺之間的移植過程宙彪,因為編譯一個子系統(tǒng)不會影響其他的子系統(tǒng),也不會影響外觀對象有巧。
外觀(Facade)模式的主要缺點如下。
1.不能很好地限制客戶使用子系統(tǒng)類悲没。
2.增加新的子系統(tǒng)可能需要修改外觀類或客戶端的源代碼篮迎,違背了“開閉原則”男图。
2.模式的實現(xiàn)
package facade;
public class FacadePattern
{
public static void main(String[] args)
{
Facade f=new Facade();
f.method();
}
}
//外觀角色
class Facade
{
private SubSystem01 obj1=new SubSystem01();
private SubSystem02 obj2=new SubSystem02();
private SubSystem03 obj3=new SubSystem03();
public void method()
{
obj1.method1();
obj2.method2();
obj3.method3();
}
}
//子系統(tǒng)角色
class SubSystem01
{
public void method1()
{
System.out.println("子系統(tǒng)01的method1()被調(diào)用!");
}
}
//子系統(tǒng)角色
class SubSystem02
{
public void method2()
{
System.out.println("子系統(tǒng)02的method2()被調(diào)用甜橱!");
}
}
//子系統(tǒng)角色
class SubSystem03
{
public void method3()
{
System.out.println("子系統(tǒng)03的method3()被調(diào)用逊笆!");
}
}
3.應用場景
1.對分層結(jié)構(gòu)系統(tǒng)構(gòu)建時,使用外觀模式定義子系統(tǒng)中每層的入口點可以簡化子系統(tǒng)之間的依賴關(guān)系岂傲。
2.當一個復雜系統(tǒng)的子系統(tǒng)很多時难裆,外觀模式可以為系統(tǒng)設(shè)計一個簡單的接口供外界訪問。
3.當客戶端與多個子系統(tǒng)之間存在很大的聯(lián)系時镊掖,引入外觀模式可將它們分離乃戈,從而提高子系統(tǒng)的獨立性和可移植性。
------行為型模式-------
1.模板方法模式
1.定義與特點
定義一個操作中的算法骨架亩进,而將算法的一些步驟延遲到子類中症虑,使得子類可以不改變該算法結(jié)構(gòu)的情況下重定義該算法的某些特定步驟。它是一種類行為型模式归薛。
該模式的主要優(yōu)點如下谍憔。
1.它封裝了不變部分,擴展可變部分主籍。它把認為是不變部分的算法封裝到父類中實現(xiàn)习贫,而把可變部分算法由子類繼承實現(xiàn),便于子類繼續(xù)擴展千元。
2.它在父類中提取了公共的部分代碼苫昌,便于代碼復用。
3.部分方法是由子類實現(xiàn)的诅炉,因此子類可以通過擴展方式增加相應的功能蜡歹,符合開閉原則。
該模式的主要缺點如下涕烧。
1.對每個不同的實現(xiàn)都需要定義一個子類月而,這會導致類的個數(shù)增加,系統(tǒng)更加龐大议纯,設(shè)計也更加抽象父款。
2.父類中的抽象方法由子類實現(xiàn),子類執(zhí)行的結(jié)果會影響父類的結(jié)果瞻凤,這導致一種反向的控制結(jié)構(gòu)憨攒,它提高了代碼閱讀的難度。
2.模式的實現(xiàn)
package templateMethod;
public class TemplateMethodPattern
{
public static void main(String[] args)
{
AbstractClass tm=new ConcreteClass();
tm.TemplateMethod();
}
}
//抽象類
abstract class AbstractClass
{
public void TemplateMethod() //模板方法
{
SpecificMethod();
abstractMethod1();
abstractMethod2();
}
public void SpecificMethod() //具體方法
{
System.out.println("抽象類中的具體方法被調(diào)用...");
}
public abstract void abstractMethod1(); //抽象方法1
public abstract void abstractMethod2(); //抽象方法2
}
//具體子類
class ConcreteClass extends AbstractClass
{
public void abstractMethod1()
{
System.out.println("抽象方法1的實現(xiàn)被調(diào)用...");
}
public void abstractMethod2()
{
System.out.println("抽象方法2的實現(xiàn)被調(diào)用...");
}
}
3.應用場景
1.算法的整體步驟很固定阀参,但其中個別部分易變時肝集,這時候可以使用模板方法模式,將容易變的部分抽象出來蛛壳,供子類實現(xiàn)杏瞻。
2.當多個子類存在公共的行為時所刀,可以將其提取出來并集中到一個公共父類中以避免代碼重復。首先捞挥,要識別現(xiàn)有代碼中的不同之處浮创,并且將不同之處分離為新的操作。最后砌函,用一個調(diào)用這些新的操作的模板方法來替換這些不同的代碼斩披。
3.當需要控制子類的擴展時,模板方法只在特定點調(diào)用鉤子操作讹俊,這樣就只允許在這些點進行擴展垦沉。
2.策略模式
1.定義與特點
該模式定義了一系列算法,并將每個算法封裝起來劣像,使它們可以相互替換乡话,且算法的變化不會影響使用算法的客戶。策略模式屬于對象行為模式耳奕,它通過對算法進行封裝绑青,把使用算法的責任和算法的實現(xiàn)分割開來,并委派給不同的對象對這些算法進行管理屋群。
2.模式的實現(xiàn)
package strategy;
public class StrategyPattern
{
public static void main(String[] args)
{
Context c=new Context();
Strategy s=new ConcreteStrategyA();
c.setStrategy(s);
c.strategyMethod();
System.out.println("-----------------");
s=new ConcreteStrategyB();
c.setStrategy(s);
c.strategyMethod();
}
}
//抽象策略類
interface Strategy
{
public void strategyMethod(); //策略方法
}
//具體策略類A
class ConcreteStrategyA implements Strategy
{
public void strategyMethod()
{
System.out.println("具體策略A的策略方法被訪問闸婴!");
}
}
//具體策略類B
class ConcreteStrategyB implements Strategy
{
public void strategyMethod()
{
System.out.println("具體策略B的策略方法被訪問!");
}
}
//環(huán)境類
class Context
{
private Strategy strategy;
public Strategy getStrategy()
{
return strategy;
}
public void setStrategy(Strategy strategy)
{
this.strategy=strategy;
}
public void strategyMethod()
{
strategy.strategyMethod();
}
}
3.應用場景
- 一個系統(tǒng)需要動態(tài)地在幾種算法中選擇一種時芍躏,可將每個算法封裝到策略類中邪乍。
- 一個類定義了多種行為,并且這些行為在這個類的操作中以多個條件語句的形式出現(xiàn)对竣,可將每個條件分支移入它們各自的策略類中以代替這些條件語句量窘。
- 系統(tǒng)中各算法彼此完全獨立蔬浙,且要求對客戶隱藏具體算法的實現(xiàn)細節(jié)時祠汇。
- 系統(tǒng)要求使用算法的客戶不應該知道其操作的數(shù)據(jù)時怠晴,可使用策略模式來隱藏與算法相關(guān)的數(shù)據(jù)結(jié)構(gòu)。
- 多個類只區(qū)別在表現(xiàn)行為不同临燃,可以使用策略模式睛驳,在運行時動態(tài)選擇具體要執(zhí)行的行為。
3.責任鏈模式
1.定義與特點
為了避免請求發(fā)送者與多個請求處理者耦合在一起膜廊,將所有請求的處理者通過前一對象記住其下一個對象的引用而連成一條鏈乏沸;當有請求發(fā)生時,可將請求沿著這條鏈傳遞爪瓜,直到有對象處理它為止蹬跃。
降低了對象之間的耦合度。該模式使得一個對象無須知道到底是哪一個對象處理其請求以及鏈的結(jié)構(gòu)铆铆,發(fā)送者和接收者也無須擁有對方的明確信息蝶缀。
1.增強了系統(tǒng)的可擴展性辆苔。可以根據(jù)需要增加新的請求處理類扼劈,滿足開閉原則。
2.增強了給對象指派職責的靈活性菲驴。當工作流程發(fā)生變化荐吵,可以動態(tài)地改變鏈內(nèi)的成員或者調(diào)動它們的次序,也可動態(tài)地新增或者刪除責任赊瞬。
3.責任鏈簡化了對象之間的連接先煎。每個對象只需保持一個指向其后繼者的引用,不需保持其他所有處理者的引用巧涧,這避免了使用眾多的 if 或者 if···else 語句薯蝎。
4.責任分擔。每個類只需要處理自己該處理的工作谤绳,不該處理的傳遞給下一個對象完成占锯,明確各類的責任范圍,符合類的單一職責原則缩筛。
2.模式的實現(xiàn)
package chainOfResponsibility;
public class LeaveApprovalTest
{
public static void main(String[] args)
{
//組裝責任鏈
Leader teacher1=new ClassAdviser();
Leader teacher2=new DepartmentHead();
Leader teacher3=new Dean();
//Leader teacher4=new DeanOfStudies();
teacher1.setNext(teacher2);
teacher2.setNext(teacher3);
//teacher3.setNext(teacher4);
//提交請求
teacher1.handleRequest(8);
}
}
//抽象處理者:領(lǐng)導類
abstract class Leader
{
private Leader next;
public void setNext(Leader next)
{
this.next=next;
}
public Leader getNext()
{
return next;
}
//處理請求的方法
public abstract void handleRequest(int LeaveDays);
}
//具體處理者1:班主任類
class ClassAdviser extends Leader
{
public void handleRequest(int LeaveDays)
{
if(LeaveDays<=2)
{
System.out.println("班主任批準您請假" + LeaveDays + "天消略。");
}
else
{
if(getNext() != null)
{
getNext().handleRequest(LeaveDays);
}
else
{
System.out.println("請假天數(shù)太多,沒有人批準該假條瞎抛!");
}
}
}
}
//具體處理者2:系主任類
class DepartmentHead extends Leader
{
public void handleRequest(int LeaveDays)
{
if(LeaveDays<=7)
{
System.out.println("系主任批準您請假" + LeaveDays + "天艺演。");
}
else
{
if(getNext() != null)
{
getNext().handleRequest(LeaveDays);
}
else
{
System.out.println("請假天數(shù)太多,沒有人批準該假條桐臊!");
}
}
}
}
//具體處理者3:院長類
class Dean extends Leader
{
public void handleRequest(int LeaveDays)
{
if(LeaveDays<=10)
{
System.out.println("院長批準您請假" + LeaveDays + "天胎撤。");
}
else
{
if(getNext() != null)
{
getNext().handleRequest(LeaveDays);
}
else
{
System.out.println("請假天數(shù)太多,沒有人批準該假條断凶!");
}
}
}
}
//具體處理者4:教務處長類
class DeanOfStudies extends Leader
{
public void handleRequest(int LeaveDays)
{
if(LeaveDays<=20)
{
System.out.println("教務處長批準您請假"+LeaveDays+"天伤提。");
}
else
{
if(getNext()!=null)
{
getNext().handleRequest(LeaveDays);
}
else
{
System.out.println("請假天數(shù)太多,沒有人批準該假條懒浮!");
}
}
}
}
3.應用場景
1.有多個對象可以處理一個請求飘弧,哪個對象處理該請求由運行時刻自動確定。
2.可動態(tài)指定一組對象處理請求砚著,或添加新的處理者次伶。
3.在不明確指定請求處理者的情況下,向多個處理者中的一個提交請求稽穆。
4.觀察者模式
1.定義與特點
指多個對象間存在一對多的依賴關(guān)系冠王,當一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新舌镶。這種模式有時又稱作發(fā)布-訂閱模式柱彻、模型-視圖模式豪娜,它是對象行為型模式。
觀察者模式是一種對象行為型模式哟楷,其主要優(yōu)點如下瘤载。
1.降低了目標與觀察者之間的耦合關(guān)系,兩者之間是抽象耦合關(guān)系卖擅。
2.目標與觀察者之間建立了一套觸發(fā)機制鸣奔。
2.模式的實現(xiàn)
package observer;
import java.util.*;
public class RMBrateTest
{
public static void main(String[] args)
{
Rate rate=new RMBrate();
Company watcher1=new ImportCompany();
Company watcher2=new ExportCompany();
rate.add(watcher1);
rate.add(watcher2);
rate.change(10);
rate.change(-9);
}
}
//抽象目標:匯率
abstract class Rate
{
protected List<Company> companys=new ArrayList<Company>();
//增加觀察者方法
public void add(Company company)
{
companys.add(company);
}
//刪除觀察者方法
public void remove(Company company)
{
companys.remove(company);
}
public abstract void change(int number);
}
//具體目標:人民幣匯率
class RMBrate extends Rate
{
public void change(int number)
{
for(Company obs:companys)
{
((Company)obs).response(number);
}
}
}
//抽象觀察者:公司
interface Company
{
void response(int number);
}
//具體觀察者1:進口公司
class ImportCompany implements Company
{
public void response(int number)
{
if(number>0)
{
System.out.println("人民幣匯率升值"+number+"個基點,降低了進口產(chǎn)品成本惩阶,提升了進口公司利潤率挎狸。");
}
else if(number<0)
{
System.out.println("人民幣匯率貶值"+(-number)+"個基點,提升了進口產(chǎn)品成本断楷,降低了進口公司利潤率锨匆。");
}
}
}
//具體觀察者2:出口公司
class ExportCompany implements Company
{
public void response(int number)
{
if(number>0)
{
System.out.println("人民幣匯率升值"+number+"個基點,降低了出口產(chǎn)品收入冬筒,降低了出口公司的銷售利潤率恐锣。");
}
else if(number<0)
{
System.out.println("人民幣匯率貶值"+(-number)+"個基點,提升了出口產(chǎn)品收入账千,提升了出口公司的銷售利潤率侥蒙。");
}
}
}
3.應用場景
1.對象間存在一對多關(guān)系,一個對象的狀態(tài)發(fā)生改變會影響其他對象匀奏。
2.當一個抽象模型有兩個方面鞭衩,其中一個方面依賴于另一方面時,可將這二者封裝在獨立的對象中以使它們可以各自獨立地改變和復用娃善。
4.UML
1.類
類是面向?qū)ο笙到y(tǒng)組織結(jié)構(gòu)的核心论衍,它是對一組具有相同屬性、操作聚磺、關(guān)系和語義的對象的抽象坯台。在 UML 中,類使用帶有分隔線的矩形來表示瘫寝,它包括名稱部分(Name)蜒蕾、屬性部分(Attribute)和操作部分(Operation)。
其中焕阿,屬性的表示形式是:[可見性]屬性名:類型[=默認值]
操作的表示形式是:[可見性]名稱(參數(shù)列表)[:返回類型]
注意:“可見性”包括公有(public)咪啡、私有(private)、受保護(protected)和朋友(fiiendly)等 4 種暮屡,在類圖中分別用符號+撤摸、-、#、~來表示准夷。
圖 3 所示是類的 UML 圖形表示方式钥飞。
2.類之間的關(guān)系
在軟件系統(tǒng)中,類不是孤立存在的衫嵌,類與類之間存在各種關(guān)系读宙。根據(jù)類與類之間的耦合度從弱到強排列,有依賴關(guān)系楔绞、關(guān)聯(lián)關(guān)系论悴、聚合關(guān)系、組合關(guān)系墓律、泛化關(guān)系和實現(xiàn)關(guān)系等 6 種,它們的功能在UML中的類圖及類圖之間的關(guān)系一文中已經(jīng)介紹幔亥,下面介紹它們在 UML 中的表示方式耻讽。
1.依賴關(guān)系(Dependency),使用帶箭頭的虛線來表示帕棉,箭頭從使用類指向被依賴的類针肥。
2.關(guān)聯(lián)關(guān)系(Association),分為雙向關(guān)聯(lián)和單向關(guān)聯(lián)兩種香伴。其中慰枕,雙向關(guān)聯(lián)可以用帶兩個箭頭或者沒有箭頭的實線來表示,單向關(guān)聯(lián)用帶一個箭頭的實線來表示即纲,箭頭從使用類指向被關(guān)聯(lián)的類具帮。還可以在關(guān)聯(lián)線的兩端標注角色名,補充說明它們的角色低斋。
3.聚合關(guān)系(Aggregation)蜂厅,用帶空心菱形的實線來表示,菱形指向整體膊畴。
4.組合關(guān)系(Composition)掘猿,用帶實心菱形的實線來表示,菱形指向整體唇跨。
5.泛化關(guān)系(Generalization)稠通,用帶空心三角箭頭的實線來表示,箭頭從子類指向父類买猖。
6.實現(xiàn)關(guān)系(Realization)改橘,用帶空心三角箭頭的虛線來表示,箭頭從實現(xiàn)類指向接口政勃。
圖 4 所示是類之間的關(guān)系在 UML 中的圖形表示方式唧龄。