java23種設計者模式 + 例子
java的設計模式大體上分為三大類(個人理解):
*建立型模式(4種):工廠模式,單例模式,建造者模式,原型模式
*結構型模式(7種):介面卡模式,裝飾器模式,代理模式,外觀模式,橋接模式,組合模式,享元模式
*行為型模式(11種):策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、直譯器模式
設計模式遵循的6個原則:
1、開閉原則
對擴充套件開放,對修改關閉
2、里氏代換原則
只有當衍生類可以替換掉基類,軟體單位的功能不受到影響時,基類才能真正被複用,而衍生類也能夠在基類的基礎上增加新的行為
3、依賴倒轉原則
這個是開閉原則的基礎,對介面程式設計,依賴於抽象而不依賴於具體。
4、介面隔離原則
使用多個隔離的藉口來降低耦合度。
5、迪米特法則(最少知道原則)
一個實體應當儘量少的與其他實體之間發生相互作用,使得系統功能模組相對獨立。
6、合成複用原則
原則是儘量使用合成/聚合的方式,而不是使用繼承。繼承實際上破壞了類的封裝性,超類的方法可能會被子類修改。
一、工廠模式(Factory)
例項1:追MM少不了請吃飯了,麥當勞的雞翅和肯德基的雞翅都是MM愛吃的東西,雖然口味有所不同,但不管你帶MM去麥當勞或肯德基,只管向服務員說“來四個雞翅”就行了。麥當勞和肯德基就是生產雞翅的Factory 。
public class Factory {
public static Sample creator(int which){
//getClass 產生Sample 一般可使用動態類裝載裝入類。
if (which== 1)
return new SampleA();
else if (which== 2)
return new SampleB();
}
}
例項2:請MM去麥當勞吃漢堡,不同的MM有不同的口味,要每個都記住是一件煩人的事情,我一般採用Factory Method模式,帶著MM到服務員那兒,說“要一個漢堡”,具體要什麼樣的漢堡呢,讓MM直接跟服務員說就行了。
public abstract class Factory{
public abstract Sample creator();
}
public class AFactory extends Factory{
public Sample creator(){
.........
return new SampleA ();
}
}
public class BFactory extends Factory{
public Sample creator(){
.........
return new SampleB ();
}
}
二、建造模式(Builder)
例項:MM最愛聽的就是“我愛你”這句話了,見到不同地方的MM,要能夠用她們的方言跟她說這句話哦,我有一個多種語言翻譯機,上面每種語言都有一個按鍵,見到MM我只要按對應的鍵,它就能夠用相應的語言說出“我愛你”這句話了,國外的MM也可以輕鬆搞掂,這就是我的“我愛你”builder。
public interface Builder {
//建立部件A 比如建立汽車車輪
void buildPartA();
//建立部件B 比如建立汽車方向盤
void buildPartB();
//建立部件C 比如建立汽車發動機
void buildPartC();
//返回最後組裝成品結果 (返回最後裝配好的汽車)
//成品的組裝過程不在這裡進行,而是轉移到下面的Director類別中進行。
//從而實現瞭解耦過程和部件
Product getResult();
}
public class Director {
private Builder builder;
public Director( Builder builder ) {
this.builder = builder;
}
// 將部件partA partB partC最後組成複雜物件
//這裡是將車輪 方向盤和發動機組裝成汽車的過程
public void construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}
三、原始模型模式(Prototype)
例項:跟MM用QQ聊天,一定要說些深情的話語了,我搜集了好多肉麻的情話,需要時只要copy出來放到QQ裡面就行了,這就是我的情話prototype了。
public abstract class AbstractSpoon implements Cloneable {
String spoonName;
public void setSpoonName(String spoonName) {
this.spoonName = spoonName;
}
public String getSpoonName() {
return this.spoonName;
}
public Object clone() {
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException exception) {
System.err.println("AbstractSpoon is not Cloneable");
}
return object;
}
}
public class SoupSpoon extends AbstractSpoon {
public SoupSpoon(){
setSpoonName("Soup Spoon");
}
}
public class SaladSpoon extends AbstractSpoon{
public SoupSpoon(){
setSpoonName("Salad Spoon");
}
}
四、單例模式(Singleton)
1、一個類只有一個例項
2、提供一個全域性訪問點
3、禁止拷貝
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
if (instance==null)
instance=new Singleton();
return instance;
}
}
五、介面卡(Adapter)
例項:在朋友聚會上碰到了一個美女Sarah,從香港來的,可我不會說粵語,她不會說普通話,只好求助於我的朋友kent了,他作為我和Sarah之間的Adapter,讓我和Sarah可以相互交談了。
public interface IRoundPeg{
public void insertIntoHole(String msg);
}
public interface ISquarePeg{
public void insert(String str);
}
public class PegAdapter implements IRoundPeg,ISquarePeg{
private RoundPeg roundPeg;
private SquarePeg squarePeg;
// 構造方法1
public PegAdapter(RoundPeg peg){
this.roundPeg=peg;
}
// 構造方法2
public PegAdapter(SquarePeg peg)(
this.squarePeg=peg;
}
public void insert(String str){
roundPeg.insertIntoHole(str);
}
public void insertIntoHole(String str){
SquarePeg.insert(str);
}
}
六、橋樑模式(Bridge)
例項:早上碰到MM,要說早上好,晚上碰到MM,要說晚上好;碰到MM穿了件新衣服,要說你的衣服好漂亮哦,碰到MM新做的髮型,要說你的頭髮好漂亮哦。不要問我“早上碰到MM新做了個髮型怎麼說”這種問題,自己用BRIDGE組合一下不就行了 。
public abstract class Coffee {
CoffeeImp coffeeImp;
public void setCoffeeImp() {
this.CoffeeImp = CoffeeImpSingleton.getTheCoffeImp();
}
public SodaImp getCoffeeImp() {
return this.CoffeeImp;
}
public abstract void pourCoffee();
}
public abstract class CoffeeImp {
public abstract void pourCoffeeImp();
}
//bridge
public class CoffeeImpSingleton {
private static CoffeeImp coffeeImp;
public CoffeeImpSingleton(CoffeeImp coffeeImpIn){
this.coffeeImp = coffeeImpIn;
}
public static CoffeeImp getTheCoffeeImp() {
return coffeeImp;
}
}
七、合成模式(Composite)
例項:Mary今天過生日。“我過生日,你要送我一件禮物。”“嗯,好吧,去商店,你自己挑。”“這件T恤挺漂亮,買,這條裙子好看,買,這個包也不錯,買。”“喂,買了三件了呀,我只答應送一件禮物的哦。”“什麼呀,T恤加裙子加包包,正好配成一套呀,小姐,麻煩你包起來。”“……”,MM都會用Composite模式了,你會了沒有?
public abstract class Equipment {
private String name;
public abstract double netPrice();
public abstract double discountPrice();
//增加部件方法
public boolean add(Equipment equipment) {
return false;
}
//刪除部件方法
public boolean remove(Equipment equipment) {
return false;
}
//注意這裡,這裡就提供一種用於訪問組合體類別的部件方法。
public Iterator iter() {
return null;
}
public Equipment(final String name) {
this.name=name;
}
}
八、裝飾模式(Decorator)
例項:Mary過完輪到Sarly過生日,還是不要叫她自己挑了,不然這個月伙食費肯定玩完,拿出我去年在華山頂上照的照片,在背面寫上“最好的的禮物,就是愛你的Fita”,再到街上禮品店買了個像框(賣禮品的MM也很漂亮哦),再找隔壁搞美術設計的Mike設計了一個漂亮的盒子裝起來……,我們都是Decorator,最終都在修飾我這個人呀,怎麼樣,看懂了嗎?
public interface Work {
public void insert();
}
public class SquarePeg implements Work{
public void insert(){
System.out.println("方形樁插入");
}
}
public class Decorator implements Work{
private Work work; //額外增加的功能被打包在這個List中
private ArrayList others = new ArrayList();
//在構造器中使用組合new方式,引入Work物件;
public Decorator(Work work) {
this.work=work;
others.add("挖坑");
others.add("釘木板");
}
public void insert(){
newMethod();
}
//在新方法中,我們在insert之前增加其他方法,這裡次序先後是使用者靈活指定的
public void newMethod(){
otherMethod();
work.insert();
}
public void otherMethod(){
ListIterator listIterator = others.listIterator();
while (listIterator.hasNext()){
System.out.println(((String)(listIterator.next())) + " 正在進行");
}
}
}
九、門面模式(Facade)
例項:我有一個專業的Nikon相機,我就喜歡自己手動調光圈、快門,這樣照出來的照片才專業,但MM可不懂這些,教了半天也不會。幸好相機有Facade設計模式,把相機調整到自動檔,只要對準目標按快門就行了,一切由相機自動調整,這樣MM也可以用這個相機給我拍張照片了。
public class DBCompare {
String sql = "SELECT * FROM <table> WHERE <column name> = ?";
try {
Mysql msql=new mysql(sql);
prep.setString( 1, "<column value>" );
rset = prep.executeQuery();
if( rset.next() ) {
System.out.println( rset.getString( "<column name" ));
}
} catch( SException e ) {
e.printStackTrace();
} finally {
mysql.close();
mysql=null;
}
}
十、享元模式(Flyweight)
例項:每天跟MM發簡訊,手指都累死了,最近買了個新手機,可以把一些常用的句子存在手機裡,要用的時候,直接拿出來,在前面加上MM的名字就可以傳送了,再不用一個字一個字敲了。共享的句子就是Flyweight,MM的名字就是提取出來的外部特徵,根據上下文情況使用。
public class CD {
private String title;
private int year;
private Artist artist;
public String getTitle() {
return title;
}
public int getYear() {
return year;
}
public Artist getArtist() {
return artist;
}
public void setTitle(String t){
title = t;
}
public void setYear(int y){
year = y;
}
public void setArtist(Artist a){
artist = a;
}
}
public class Artist {
//內部狀態
private String name;
// note that Artist is immutable.
String getName(){
return name;
}
Artist(String n){
name = n;
}
}
public class ArtistFactory {
Hashtable pool = new Hashtable();
Artist getArtist(String key){
Artist result;
result = (Artist)pool.get(key);
////産生新的Artist
if(result == null) {
result = new Artist(key);
pool.put(key,result);
}
return result;
}
}
十一、代理模式(Proxy)
例項:跟MM在網上聊天,一開頭總是“hi,你好”,“你從哪兒來呀?”“你多大了?”“身高多少呀?”這些話,真煩人,寫個程式做為我的Proxy吧,凡是接收到這些話都設定好了自動的回答,接收到其他的話時再通知我回答。
public class ForumPermissions implements Cacheable;
public class ForumProxy implements Forum;
public class DbForum implements Forum, Cacheable
十二、職責鏈(Chain of Responsibility)
例項:晚上去上英語課,為了好開溜坐到了最後一排,哇,前面坐了好幾個漂亮的MM哎,找張紙條,寫上“Hi,可以做我的女朋友嗎?如果不願意請向前傳”,紙條就一個接一個的傳上去了,糟糕,傳到第一排的MM把紙條傳給老師了,聽說是個老處女呀,快跑!
public interface Handler{
public void handleRequest(Request request);
}
public class Request{
private String type;
public Request(String type){this.type=type;}
public String getType(){return type;}
public void execute(){
//request真正具體行為程式碼
}
}
public class ConcreteHandler implements Handler{
private Handler successor;
public ConcreteHandler(Handler successor){
this.successor=successor;
}
public void handleRequest(Request request){
if (request instanceof HelpRequest){
//這裡是處理Help的具體程式碼
}else if (request instanceof PrintRequst){
request.execute();
}else
//傳遞到下一個
successor.handle(request);
}
}
}
十三、命令模式(Command)
例項:俺有一個MM家裡管得特別嚴,沒法見面,只好藉助於她弟弟在我們倆之間傳送資訊,她對我有什麼指示,就寫一張紙條讓她弟弟帶給我。這不,她弟弟又傳送過來一個COMMAND,為了感謝他,我請他吃了碗雜醬麵,哪知道他說:“我同時給我姐姐三個男朋友送COMMAND,就數你最小氣,才請我吃麵。”
public interface Command {
public abstract void execute ( );
}
public class producer{
public static List produceRequests() {
List queue = new ArrayList();
queue.add( new DomesticEngineer() );
queue.add( new Politician() );
queue.add( new Programmer() );
return queue;
}
}
public class TestCommand {
public static void main(String[] args) {
List queue = Producer.produceRequests();
for (Iterator it = queue.iterator(); it.hasNext(); )
//取出List中東東,其他特徵都不能確定,只能保證一個特徵是100%正確,
// 他們至少是介面Command的"兒子"。所以強制轉換類別型為介面Command
((Command)it.next()).execute();
}
}
十四、直譯器模式(Interpreter)
例項:俺有一個《泡MM真經》,上面有各種泡MM的攻略,比如說去吃西餐的步驟、去看電影的方法等等,跟MM約會時,只要做一個Interpreter,照著上面的指令碼執行就可以了。
十五、迭代子模式(Iterator)
例項:
我愛上了Mary,不顧一切的向她求婚。
Mary:“想要我跟你結婚,得答應我的條件”
我:“什麼條件我都答應,你說吧”
Mary:“我看上了那個一克拉的鑽石”
我:“我買,我買,還有嗎?”
Mary:“我看上了湖邊的那棟別墅”
我:“我買,我買,還有嗎?”
Mary:“我看上那輛法拉利跑車”
我腦袋嗡的一聲,坐在椅子上,一咬牙:“我買,我買,還有嗎?”
//用來遍曆Collection中物件
public class TestCommand {
public static void main(String[] args) {
List queue = Producer.produceRequests();
for (Iterator it = queue.iterator(); it.hasNext(); )
//取出List中東東,其他特徵都不能確定,只能保證一個特徵是100%正確,
// 他們至少是介面Command的"兒子"。所以強制轉換類別型為介面Command
((Command)it.next()).execute();
}
}
十六、調停者模式(Mediator)
例項:四個MM打麻將,相互之間誰應該給誰多少錢算不清楚了,幸虧當時我在旁邊,按照各自的籌碼數算錢,賺了錢的從我這裡拿,賠了錢的也付給我,一切就OK啦,俺得到了四個MM的電話。
public interface Mediator { }
public class ConcreteMediator implements Mediator { //假設當前有兩個成員.
private ConcreteColleague1 colleague1 = new ConcreteColleague1();
private ConcreteColleague2 colleague2 = new ConcreteColleague2();
... }
public class Colleague {
private Mediator mediator;
public Mediator getMediator() {
return mediator;
}
public void setMediator( Mediator mediator ) {
this.mediator = mediator;
}
}
public class ConcreteColleague1 { }
pu