摘要:創(chuàng)建型設(shè)計(jì)模式結(jié)構(gòu)型設(shè)計(jì)模式行為型設(shè)計(jì)模式結(jié)構(gòu)型設(shè)計(jì)模式簡(jiǎn)而言之結(jié)構(gòu)模式主要涉及對(duì)象的組成,或者是實(shí)體如何相互使用。
1.創(chuàng)建型設(shè)計(jì)模式
2.結(jié)構(gòu)型設(shè)計(jì)模式
3.行為型設(shè)計(jì)模式
簡(jiǎn)而言之
結(jié)構(gòu)模式主要涉及對(duì)象的組成,或者是實(shí)體如何相互使用?;蛘撸硪粋€(gè)解釋是,他們幫助回答“如何構(gòu)建一個(gè)軟件組件?”
維基百科說
在軟件工程中,結(jié)構(gòu)設(shè)計(jì)模式是通過識(shí)別實(shí)體之間關(guān)系的簡(jiǎn)單方法來簡(jiǎn)化設(shè)計(jì)的設(shè)計(jì)模式。?適配器模式
現(xiàn)實(shí)舉例
考慮一下你的記憶卡上有一些圖片,你需要把它們轉(zhuǎn)移到你的電腦上。為了轉(zhuǎn)移它們,你需要某種與你的計(jì)算機(jī)端口兼容的適配器,這樣你就可以將存儲(chǔ)卡附加到你的電腦上。在這個(gè)例子中讀卡器就是適配器。
另一個(gè)例子是著名的電源適配器;一個(gè)三腳插頭不能連接到兩個(gè)電源插座,它需要使用一個(gè)電源適配器,使它與兩個(gè)電源插座兼容。
另一個(gè)例子是一個(gè)譯者翻譯一個(gè)人對(duì)另一個(gè)人說的話。
簡(jiǎn)而言之
適配器模式允許您在適配器中包裝一個(gè)不兼容的對(duì)象,使其與另一個(gè)類兼容。
維基百科說
在軟件工程中,適配器模式是一種軟件設(shè)計(jì)模式,它允許將現(xiàn)有類的接口用作另一個(gè)接口。它通常用于使現(xiàn)有的類與其他類一起工作,而無需修改它們的源代碼。
編程示例
考慮一個(gè)游戲,一個(gè)獵人追捕獅子。
首先我有一個(gè)獅子(Lion)的接口和所有要實(shí)現(xiàn)類型的獅子。
public interface Lion { void roar(); }
public class AsianLion implements Lion { @Override public void roar() { System.out.println("AsianLion roar"); } }
public class AfricanLion implements Lion { @Override public void roar() { System.out.println("AfricanLion roar"); } }
獵人希望所有捕獲的獅子都能實(shí)現(xiàn)Lion的接口。
public class Hunter { public void hunt(Lion lion) { lion.roar(); } }
現(xiàn)在在我們的游戲里增加一個(gè)"野狗"(WildDog),獵人也可以捕獲。但是我們不能直接這樣做,因?yàn)橐肮?WildDog)有一個(gè)不同的接口。為了兼容我們的獵人(hunter),我們必須創(chuàng)建一個(gè)適配器來使之兼容。
public class WildDog { public void bark() { System.out.println("WildDog bark"); } }
public class WildDogAdapter implements Lion { private WildDog wildDog; public WildDogAdapter(WildDog wildDog) { this.wildDog = wildDog; } @Override public void roar() { this.wildDog.bark(); } }
現(xiàn)在 WildDog 可以在我們的游戲里使用 WildDogAdapter來代替.
WildDog wildDog = new WildDog(); WildDogAdapter adapter = new WildDogAdapter(wildDog); Hunter hunter = new Hunter(); hunter.hunt(adapter);?橋接模式
現(xiàn)實(shí)舉例
考慮你有一個(gè)不同頁面的網(wǎng)站,你應(yīng)該允許用戶改變主題。你會(huì)怎么做?為每個(gè)主題創(chuàng)建多個(gè)頁面的多個(gè)副本,或者僅僅根據(jù)用戶的喜好創(chuàng)建多帶帶的主題并加載它們?橋式模式允許你做第二件事。
簡(jiǎn)而言之
橋式模式是傾向于選擇組合而不是繼承。實(shí)現(xiàn)細(xì)節(jié)從層次結(jié)構(gòu)推送到另一個(gè)具有獨(dú)立層次結(jié)構(gòu)的對(duì)象。
維基百科說
橋式模式是軟件工程中使用的一種設(shè)計(jì)模式,它的意思是“將抽象與實(shí)現(xiàn)分離開來,以便兩者能夠獨(dú)立地變化”。
編程示例
翻譯一下上邊的Web頁面(Web Page)的例子。首先是獨(dú)立的WebPage層次
public interface WebPage { String getContent(); }
public class About implements WebPage { private Theme theme; public About(Theme theme) { this.theme = theme; } @Override public String getContent() { return "About page in "+theme.getColor(); } }
public class Career implements WebPage { private Theme theme; public Career(Theme theme) { this.theme = theme; } @Override public String getContent() { return "Career Page in "+theme.getColor(); } }
獨(dú)立的主題層次
public interface Theme { String getColor(); }
public class AquaTheme implements Theme { @Override public String getColor() { return "Light blue"; } }
public class DarkTheme implements Theme { @Override public String getColor() { return "Dark Black"; } }
public class LightTheme implements Theme { @Override public String getColor() { return "Off White"; } }
And both the hierarchies
Theme aquaTheme = new AquaTheme(); Theme darkTheme = new DarkTheme(); WebPage about = new About(aquaTheme); WebPage career = new Career(aquaTheme); System.out.println(career.getContent()); System.out.println(about.getContent()); System.out.println(""); about = new About(darkTheme); career = new Career(darkTheme); System.out.println(career.getContent()); System.out.println(about.getContent());? 組合模式
現(xiàn)實(shí)舉例
每個(gè)組織都是由雇員組成的。每個(gè)雇員都有相同的特性,即有工資,有一些職責(zé),可以或不可以向某人報(bào)告,可以或不可能有一些下屬等。
簡(jiǎn)而言之
組合模式允許客戶以統(tǒng)一的方式處理單個(gè)對(duì)象
維基百科說
在軟件工程中,組合模式是一個(gè)分而治之的設(shè)計(jì)模式。
組合模式描述了以相同的方式對(duì)待一組對(duì)象和單個(gè)對(duì)象。 組合的意圖是將對(duì)象“組合”到樹結(jié)構(gòu)中,以表示部分整個(gè)層次結(jié)構(gòu)。 實(shí)現(xiàn)組合模式可以讓客戶端對(duì)單個(gè)對(duì)象和組合進(jìn)行統(tǒng)一處理。
編程示例
參考我們上邊雇員的例子。我們又幾種類型的雇員。
public interface Employee { String getName(); void setSalary(float salary); float getSalary(); String getRole(); }
public class Developer implements Employee { private String name; private float salary; private String role; public Developer(String name, float salary) { this.name = name; this.salary = salary; this.role = "Developer"; } @Override public String getName() { return name; } @Override public void setSalary(float salary) { this.salary = salary; } @Override public float getSalary() { return this.salary; } @Override public String getRole() { return role; } }
public class Designer implements Employee{ private String name; private float salary; private String role; public Designer(String name, float salary) { this.name = name; this.salary = salary; this.role = "Designer"; } @Override public String getName() { return name; } @Override public void setSalary(float salary) { this.salary = salary; } @Override public float getSalary() { return this.salary; } @Override public String getRole() { return role; } }
下面我們用組織來保存幾種不同類型的雇員。
public class Orgnization { private Listemployees = new ArrayList<>(); public void addEmployee(Employee employee) { employees.add(employee); } public float getSalary() { float total = 0; for(Employee employee : employees) { total += employee.getSalary(); } return total; } }
使用方式如下
Employee employee1 = new Developer("John Doe",12000); Employee employee2 = new Designer("Jane Doe",15000); Orgnization orgnization = new Orgnization(); orgnization.addEmployee(employee1); orgnization.addEmployee(employee2); System.out.println(orgnization.getSalary());? 裝飾者模式
現(xiàn)實(shí)舉例
假設(shè)你經(jīng)營一家提供多種服務(wù)的汽車服務(wù)商店。那么如何計(jì)算要收取的費(fèi)用呢?您可以選擇一個(gè)服務(wù)并動(dòng)態(tài)地將提供的服務(wù)的價(jià)格添加到最終成本。這里的每一種服務(wù)都是裝飾者。
簡(jiǎn)而言之
裝飾者模式允許您通過將對(duì)象在一個(gè)裝飾者類的對(duì)象中進(jìn)行包裝,從而在運(yùn)行時(shí)動(dòng)態(tài)地更改對(duì)象的行為。
維基百科說
在面向?qū)ο缶幊讨?,裝飾者模式是一種設(shè)計(jì)模式,它允許將行為添加到單個(gè)對(duì)象中,無論是靜態(tài)的還是動(dòng)態(tài)的,都不會(huì)影響來自同一類的其他對(duì)象的行為。 裝飾者模式通常對(duì)堅(jiān)持單一責(zé)任原則非常有用,因?yàn)樗试S在具有獨(dú)特關(guān)注點(diǎn)的類之間劃分功能。
編程示例
我們以咖啡舉例,首先我們有一個(gè)簡(jiǎn)單的實(shí)現(xiàn)了咖啡接口的咖啡。
public interface Coffee { float getCost(); String getDescription(); }
public class SimpleCoffee implements Coffee { @Override public float getCost() { return 10; } @Override public String getDescription() { return "simpleCoffee"; } @Override public String toString() { return "SimpleCoffee"; } }
我們希望使代碼可擴(kuò)展,以便在需要時(shí)允許選項(xiàng)進(jìn)行修改。讓我們做一些附加組件(decorator)
public class MilkCoffee implements Coffee { private Coffee coffee; public MilkCoffee(Coffee coffee) { this.coffee = coffee; } @Override public float getCost() { return coffee.getCost()+2; } @Override public String getDescription() { return coffee.getDescription()+",milk"; } }
public class VanillaCoffee implements Coffee{ private Coffee coffee; public VanillaCoffee(Coffee coffee) { this.coffee = coffee; } @Override public float getCost() { return coffee.getCost()+3; } @Override public String getDescription() { return coffee.getDescription()+",vanilla"; } }
public class WhipCoffee implements Coffee { private Coffee coffee; public WhipCoffee(Coffee coffee) { this.coffee = coffee; } @Override public float getCost() { return coffee.getCost()+5; } @Override public String getDescription() { return coffee.getDescription()+",whip"; } }
Lets make a coffee now
Coffee coffee = new SimpleCoffee(); System.out.println(coffee.getCost()); System.out.println(coffee.getDescription()); coffee = new MilkCoffee(coffee); System.out.println(coffee.getCost()); System.out.println(coffee.getDescription()); coffee = new VanillaCoffee(coffee); System.out.println(coffee.getCost()); System.out.println(coffee.getDescription()); coffee = new WhipCoffee(coffee); System.out.println(coffee.getCost()); System.out.println(coffee.getDescription());? 門面模式
現(xiàn)實(shí)舉例
你怎么打開電腦?“按下電源鍵”你說!這就是你所相信的,因?yàn)槟闶褂玫氖且粋€(gè)簡(jiǎn)單的界面,電腦在外部提供,在內(nèi)部它需要做很多事情來實(shí)現(xiàn)它。這個(gè)復(fù)雜子系統(tǒng)的簡(jiǎn)單接口是一個(gè)門面。
簡(jiǎn)而言之
門面模式提供了一個(gè)復(fù)雜子系統(tǒng)的簡(jiǎn)化接口。
維基百科說
門面模式是為更大的代碼體(如類庫)提供簡(jiǎn)化接口的對(duì)象。
編程示例
以我們上邊的計(jì)算機(jī)為例。首先這是我們的計(jì)算機(jī)。
public class Computer { public void getElectricShock() { System.out.println("Ouch"); } public void makeSound() { System.out.println("Beep beep!"); } public void showLoadingScreen() { System.out.println("Loading.."); } public void bam() { System.out.println("Ready to be used!"); } public void closeEverything() { System.out.println("closeEverything"); } public void sooth() { System.out.println("Zzzzz"); } public void pullCurrent() { System.out.println("Haaah"); } }
下面是門面
public class ComputerFacade { private Computer computer; public ComputerFacade(Computer computer) { this.computer = computer; } public void turnOn() { computer.getElectricShock(); computer.makeSound(); computer.showLoadingScreen(); computer.bam(); } public void turnOff() { computer.closeEverything(); computer.pullCurrent(); computer.sooth(); } }
下面開始使用門面
Computer computer = new Computer(); ComputerFacade facade = new ComputerFacade(computer); facade.turnOn(); System.out.println("============================"); facade.turnOff();? 享元模式
現(xiàn)實(shí)舉例
你曾經(jīng)在某個(gè)攤位上喝過新鮮的茶嗎?他們經(jīng)常做的比你要求的多并把剩下的留給其他顧客,以節(jié)省資源,例如氣體等。Flyweight模式就是分享。
簡(jiǎn)而言之
它通過盡可能多地與類似對(duì)象共享來最小化內(nèi)存使用或計(jì)算開銷。
維基百科說
在計(jì)算機(jī)編程中,享元是一種軟件設(shè)計(jì)模式。享元是一個(gè)對(duì)象,它通過與其他類似對(duì)象共享盡可能多的數(shù)據(jù)來最小化內(nèi)存使用;當(dāng)一個(gè)簡(jiǎn)單的重復(fù)表示使用不可接受的內(nèi)存時(shí),它是一種使用大量對(duì)象的方法。
編程示例
翻譯一下我們上邊茶水的例子。首先我們有茶的類型和茶具。
public class KarakTea { }
public class TeaMaker { private MapavailableTea = new HashMap<>(); public KarakTea make(String preference) { if(!availableTea.containsKey(preference)) { availableTea.put(preference,new KarakTea()); } return availableTea.get(preference); } }
然后我們有茶社來接單和提供服務(wù)。
public class TeaShop { private TeaMaker teaMaker; private Maporders = new HashMap<>(); public TeaShop(TeaMaker teaMaker) { this.teaMaker = teaMaker; } public void takeOrder(String teaType,int table) { orders.put(table,teaMaker.make(teaType)); } public void serve() { Set > entrySet = orders.entrySet(); for(Map.Entry entry : entrySet) { System.out.println("Serving tea to table#"+entry.getKey()); } } }
使用方式如下
TeaMaker teaMaker = new TeaMaker(); TeaShop shop = new TeaShop(teaMaker); shop.takeOrder("less sugar", 1); shop.takeOrder("more milk", 2); shop.takeOrder("without sugar", 3); shop.serve();? 代理模式
現(xiàn)實(shí)舉例
你曾經(jīng)用過門禁卡嗎?打開這扇門有多種選擇,即可以使用門禁卡打開,也可以通過按一個(gè)繞過安全按鈕的按鈕打開。 門的主要功能是打開,但是在它上面添加了一個(gè)代理來添加一些功能。讓我用下面的代碼示例更好地解釋一下。
簡(jiǎn)而言之
使用代理模式,一個(gè)類代表另一個(gè)類的功能。
維基百科說
代理,在其最一般的形式中,是一個(gè)類作為其他東西的接口。 代理是由客戶端調(diào)用的包裝器或代理對(duì)象,以訪問實(shí)際服務(wù)對(duì)象。代理的使用可以簡(jiǎn)單地轉(zhuǎn)發(fā)到實(shí)際對(duì)象,或者提供額外的邏輯。 在代理的額外功能中可以提供,例如在實(shí)際對(duì)象上的操作是資源密集型的緩存,或者在調(diào)用實(shí)際對(duì)象的操作之前檢查先決條件。
編程示例
上邊安全門的例子。首先我們有一個(gè)門的接口和一個(gè)門的實(shí)現(xiàn)
public interface Door { void open(); void close(); }
public class LabDoor implements Door { @Override public void open() { System.out.println("Opening lab door"); } @Override public void close() { System.out.println("Closing lab door"); } }
我們有一個(gè)來歷來確保我們想要的門。
public class SecuredDoor { private Door door; public SecuredDoor(Door door) { this.door = door; } public void open(String pwd) { if(authenticate(pwd)) { door.open(); } else { System.out.println("Big no! It ain"t possible."); } } private boolean authenticate(String pwd) { return "$ecr@t".equals(pwd); } public void close() { this.door.close(); } }
使用方式如下
Door door = new LabDoor(); SecuredDoor securedDoor = new SecuredDoor(door); securedDoor.open("invalid"); //securedDoor.open("$ecr@t");
還有一個(gè)例子是某種形式的數(shù)據(jù)映射的實(shí)現(xiàn)。例如我最近編寫了一個(gè)MongoDB的ODM。在mongodb周圍利用魔術(shù)方法__call()我寫了一個(gè)代理,所有的方法調(diào)用都被代理到原生的mongo類。檢索的結(jié)果作為返回的數(shù)據(jù),如果find或者findOne的數(shù)據(jù)映射到某個(gè)類,這類將會(huì)代替cursor返回。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/71057.html
摘要:創(chuàng)建型模式主要有以下五種簡(jiǎn)單工廠模式和工廠方法模式抽象工廠模式單例模式建造者模式原型模式在設(shè)計(jì)模式一書中將工廠模式分為兩類工廠方法模式與抽象工廠模式。 一、 設(shè)計(jì)模式(Design pattern)是什么 設(shè)計(jì)模式是一套被反復(fù)使用、多數(shù)人知曉、經(jīng)過分類編目的代碼設(shè)計(jì)的經(jīng)驗(yàn)總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 二、 為什么會(huì)有設(shè)計(jì)模式 在軟件開發(fā)過...
摘要:里氏代換原則里氏代換原則面向?qū)ο笤O(shè)計(jì)的基本原則之一。里氏代換原則中說,任何基類可以出現(xiàn)的地方,子類一定可以出現(xiàn)。里氏代換原則是對(duì)開閉原則的補(bǔ)充。而基類與子類的繼承關(guān)系就是抽象化的具體實(shí)現(xiàn),所以里氏代換原則是對(duì)實(shí)現(xiàn)抽象化的具體步驟的規(guī)范。 一、設(shè)計(jì)模式的六大原則: 1、開閉原則(Open Close Principle) 開閉原則就是說對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。在程序需要進(jìn)行拓展的時(shí)候,不...
摘要:遵循特定規(guī)則,利用操作符,終止節(jié)點(diǎn)和其他非終止節(jié)點(diǎn),構(gòu)造新的字符串非終結(jié)符是表示字符串的樹的內(nèi)部節(jié)點(diǎn)。語法中的生產(chǎn)具有這種形式非終結(jié)符終結(jié),非終結(jié)符和運(yùn)算符的表達(dá)式語法的非終結(jié)點(diǎn)之一被指定為根。 大綱 基于狀態(tài)的構(gòu)建 基于自動(dòng)機(jī)的編程 設(shè)計(jì)模式:Memento提供了將對(duì)象恢復(fù)到之前狀態(tài)的功能(撤消)。 設(shè)計(jì)模式:狀態(tài)允許對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變其行為。 表驅(qū)動(dòng)結(jié)構(gòu)* 基于語法的構(gòu)...
摘要:維基百科在軟件工程中,創(chuàng)建型設(shè)計(jì)模式是用于解決對(duì)象創(chuàng)建機(jī)制,嘗試在指定場(chǎng)景下使用合理的方式來創(chuàng)建對(duì)象的設(shè)計(jì)模式。維基百科說建造者模式是一種對(duì)象創(chuàng)建軟件設(shè)計(jì)模式,其目的是找到一種解決方案,以解決可伸縮構(gòu)造函數(shù)的反模式。 1.創(chuàng)建型設(shè)計(jì)模式2.結(jié)構(gòu)型設(shè)計(jì)模式3.行為型設(shè)計(jì)模式 創(chuàng)建型設(shè)計(jì)模式 簡(jiǎn)而言之 創(chuàng)建型設(shè)計(jì)模式關(guān)注的是如何實(shí)例化一個(gè)或者一組相關(guān)的對(duì)象。 維基百科 在軟件工程中,創(chuàng)建型...
閱讀 2147·2021-09-07 10:24
閱讀 2145·2019-08-30 15:55
閱讀 2122·2019-08-30 15:43
閱讀 730·2019-08-29 15:25
閱讀 1150·2019-08-29 12:19
閱讀 1999·2019-08-23 18:32
閱讀 1595·2019-08-23 17:59
閱讀 1012·2019-08-23 12:22