摘要:提供酒店相關(guān)的接口返回該時間段有效的酒店提供航班相關(guān)的接口返回該時間段有效的航班提供一個旅行對外的接口,一次返回酒店和航班信息調(diào)用旅行外觀模式享元模式享元模式主要用于減少創(chuàng)建對象的數(shù)量,以減少內(nèi)存占用和提高性能。
組合模式(Composite pattern)
組合模式看起來就像對象組的樹形結(jié)構(gòu),一個對象里面包含一個或一組其他的對象。它是屬于結(jié)構(gòu)型模式。
例如,一個公司包括很多個部門,每個部門又包括很多人,這個用數(shù)據(jù)結(jié)構(gòu)來表示就是樹形結(jié)構(gòu),實際上也是用到來組合模式,多個人組成一個部門,多個部門組成一個公司。
例如,我們用下面這個公司、部門、員工的例子來更好的理解組合模式。
class Company { private String name; private List裝飾模式(Decorator pattern)depts; } class Dept { private String name; private List users; } class User { private String name; }
裝飾器設(shè)計模式允許我們動態(tài)地向?qū)ο筇砑庸δ芎托袨?,而不會影響同一類中其他現(xiàn)有對象的行為。并且可以根據(jù)我們的要求和選擇將此自定義功能應(yīng)用于單個對象。
假如使用繼承來擴(kuò)展類的行為,這發(fā)生在編譯期,該類的所有實例都獲得擴(kuò)展行為。
裝飾器設(shè)計模式的特點(diǎn):
它允許我們在運(yùn)行時向?qū)ο螅ǘ皇穷悾┨砑庸δ堋?br>它是一種結(jié)構(gòu)模式,它為現(xiàn)有類提供了一個包裝器。
它使用抽象類或接口與組合來實現(xiàn)包裝器。
它創(chuàng)建裝飾器類,它包裝原始類并通過保持類方法的簽名不變來提供其他功能。
它最常用于應(yīng)用單一責(zé)任原則,因為我們將功能劃分為具有獨(dú)特關(guān)注區(qū)域的類。
例如,我們用下面這個畫圖形的例子來更好的理解裝飾模式。
//定義一個形狀的接口 public interface Shape { void draw(); void resize(); } //一個畫圓的實現(xiàn) public class Circle implements Shape { @Override public void draw() { System.out.println("Drawing Circle"); } @Override public void resize() { System.out.println("Resizing Circle"); } } //一個畫矩形的實現(xiàn) public class Rectangle implements Shape { @Override public void draw() { System.out.println("Drawing Rectangle"); } @Override public void resize() { System.out.println("Resizing Rectangle"); } } //定義一個形狀的裝飾器抽象類,并用組合模式定義一個形狀的屬性 public abstract class ShapeDecorator implements Shape { protected Shape decoratedShape; public ShapeDecorator(Shape decoratedShape) { super(); this.decoratedShape = decoratedShape; } } //顏色的枚舉 public enum Color { RED, GREEN, BLUE } //線條樣式的枚舉 public enum LineStyle { SOLID, DASH, DOT } //定義一個填充顏色的實現(xiàn)類實現(xiàn)裝飾器,并重寫 draw() 方法,resize() 方法我們可以保持不變,也可以自定義,看使用場景 public class FillColorDecorator extends ShapeDecorator { protected Color color; public FillColorDecorator(Shape decoratedShape, Color color) { super(decoratedShape); this.color = color; } @Override public void draw() { decoratedShape.draw(); System.out.println("Fill Color: " + color); } @Override public void resize() { decoratedShape.resize(); } } //定義一個線條樣式的實現(xiàn)類實現(xiàn)裝飾器,并重寫 draw() 方法,resize() 方法我們可以保持不變,也可以自定義,看使用場景 public class LineStyleDecorator extends ShapeDecorator { protected LineStyle style; public LineStyleDecorator(Shape decoratedShape, LineStyle style) { super(decoratedShape); this.style = style; } @Override public void draw() { decoratedShape.draw(); System.out.println("Line Style: " + style); } // @Override public void resize() { decoratedShape.resize(); } } //使用裝飾器模式 public class Client { public static void main(String[] args) { //在使用時可以任意組裝,提升代碼靈活性和擴(kuò)展性。 Shape circle = new FillColorDecorator(new LineStyleDecorator(new Circle(), LineStyle.DASH), Color.RED); circle.draw(); } }外觀模式(Facade Pattern)
它提供了一個可以訪問系統(tǒng)的接口,這個接口里面的實現(xiàn)可能很復(fù)雜,調(diào)用了其他多個接口,我們并不知道它里面的具體實現(xiàn),隱藏了系統(tǒng)的復(fù)雜性。它屬于結(jié)構(gòu)型模式。
它的優(yōu)點(diǎn):
1、減少系統(tǒng)相互依賴。
2、提高靈活性。
3、提高了安全性。
它的缺點(diǎn):
不符合開閉原則,如果要改東西很麻煩,繼承重寫都不合適。
以旅行社網(wǎng)站為例,它可以預(yù)訂酒店和航班,我們來更好的理解下這個模式。
//提供酒店相關(guān)的接口 public class HotelBooker{ public ArrayList享元模式(Flyweight Pattern)getHotelNamesFor(Date from, Date to) { //返回該時間段有效的酒店 } } //提供航班相關(guān)的接口 public class FlightBooker{ public ArrayList getFlightsFor(Date from, Date to) { //返回該時間段有效的航班 } } //提供一個旅行對外的接口,一次返回酒店和航班信息 public class TravelFacade{ private HotelBooker hotelBooker; private FlightBooker flightBooker; public void getFlightsAndHotels(Date from, Data to) { ArrayList flights = flightBooker.getFlightsFor(from, to); ArrayList hotels = hotelBooker.getHotelsFor(from, to); } } //調(diào)用旅行外觀模式 public class Client{ public static void main(String[] args) { TravelFacade facade = new TravelFacade(); facade.getFlightsAndHotels(from, to); } }
享元模式主要用于減少創(chuàng)建對象的數(shù)量,以減少內(nèi)存占用和提高性能。使許多細(xì)粒度對象的重用,使得大量對象的利用更加有效。它屬于結(jié)構(gòu)型模式。
它的優(yōu)點(diǎn):
大大減少對象的創(chuàng)建,降低系統(tǒng)的內(nèi)存,使效率提高。
它的缺點(diǎn):
因為一個對象大家共享,最好就不要有狀態(tài)區(qū)分,假如有狀態(tài)的話,
需要分離出外部狀態(tài)和內(nèi)部狀態(tài),而且外部狀態(tài)具有固有化的性質(zhì),不應(yīng)該隨著內(nèi)部狀態(tài)的變化而變化,否則會造成系統(tǒng)的混亂。
例如,我們用一個畫線條的例子來更好的理解這個模式。
//定義一個畫線條的接口 public interface LineFlyweight{ public Color getColor(); public void draw(Point location); } //定義一個畫線條的實現(xiàn) public class Line implements LineFlyweight{ private Color color; public Line(Color c){ color = c; } public Color getColor(){ return color; } public void draw(Point location){ //實現(xiàn) } } //定一個畫線條的工廠類,根據(jù)顏色來獲取線條,并且把不同顏色的線存儲在一個 pool 中,方便下次直接使用 public class LineFlyweightFactory{ private List代理模式(Proxy Pattern)pool; public LineFlyweightFactory(){ pool = new ArrayList (); } public LineFlyweight getLine(Color c){ //循環(huán)檢查這個顏色的線是否存在,存在直接返回 for(LineFlyweight line: pool){ if(line.getColor().equals(c)){ return line; } } //假如不存在,就創(chuàng)建一個放入這個 pool 中,方便下次直接使用 LineFlyweight line = new Line(c); pool.add(line); return line; } } //調(diào)用享元模式 public class Client{ public static void main(String[] args) { //調(diào)用 LineFlyweightFactory factory = new LineFlyweightFactory(); LineFlyweight line = factory.getLine(Color.RED); LineFlyweight line2 = factory.getLine(Color.RED); line.draw(new Point(100, 100)); line2.draw(new Point(200, 100)); } }
它通過一個代理類對外提供訪問,代理類在真正調(diào)用實現(xiàn)類。對外部來說,并不知道真正實現(xiàn)類的詳情,提高類系統(tǒng)的安全性。我們可以在代理類里做一系列攔截,把異常的請求都提前處理掉,擴(kuò)展性很高。它屬于結(jié)構(gòu)型模式。
它的優(yōu)點(diǎn):
1、職責(zé)清晰。
2、高擴(kuò)展性。
3、更安全。
它的缺點(diǎn):
1、由于在客戶端和真實主題之間增加了代理對象,因此可能會造成請求的處理速度變慢。
2、實現(xiàn)代理模式需要額外的工作,有些代理模式的實現(xiàn)非常復(fù)雜。
例如,我們用下面這個代理顯示圖片的例子來更好的理解代理模式。
//定義的圖片接口 public interface Image{ public void displayImage(); } //真正的實現(xiàn)類 public class RealImage implements Image{ public RealImage(URL url) { //加載這個圖片 loadImage(url); } public void displayImage() { //顯示這個圖片 } private void loadImage(URL url) { } } //代理類 public class ProxyImage implements Image{ private URL url; public ProxyImage(URL url) { this.url = url; } //this method delegates to the real image public void displayImage() { RealImage real = new RealImage(url); real.displayImage(); } } //使用代理模式 public class Client { public static void main(String[] args) { Image image = new ProxyImage("test.png"); image.display(); } }
代理模式分為靜態(tài)代理和動態(tài)代理,靜態(tài)代理的真正實現(xiàn)類是提前寫好并且編譯好的,動態(tài)代理的真正實現(xiàn)類是運(yùn)行是生成并且編譯的,上面的例子使用的是靜態(tài)代理。
動態(tài)代理又分為 JDK動態(tài)代理 和 CGLIB動態(tài)代理,JDK動態(tài)代理是基于接口的動態(tài)代理,CGLIB動態(tài)代理是基于類的代理。有興趣的可以找下相關(guān)資料。
責(zé)任鏈模式用于管理對象之間的算法,關(guān)系和責(zé)任,通過將多個不同處理對象鏈接在一起處理請求,降低耦合度,提高系統(tǒng)靈活性。它屬于行為型模式。
它的優(yōu)點(diǎn):
1、降低耦合度。
2、簡化了對象。
3、增強(qiáng)給對象指派職責(zé)的靈活性。
4、增加新的請求處理類很方便。
它的缺點(diǎn):
1、系統(tǒng)性能將受到一定影響,而且在進(jìn)行代碼調(diào)試時不太方便,可能會造成循環(huán)調(diào)用。
2、可能不容易觀察運(yùn)行時的特征,不方便排錯。
例如,我們用下面這個記錄日志的例子來更好的理解責(zé)任鏈模式。
//定義一個抽象的日志接口,并且提供一個可以設(shè)置下一個處理日志對象的方法 public abstract class AbstractLogger { public static int INFO = 1; public static int DEBUG = 2; public static int ERROR = 3; protected int level; //責(zé)任鏈中的下一個元素 protected AbstractLogger nextLogger; public void setNextLogger(AbstractLogger nextLogger){ this.nextLogger = nextLogger; } public void logMessage(int level, String message){ if(this.level <= level){ write(message); } if(nextLogger !=null){ nextLogger.logMessage(level, message); } } //抽象方法 abstract protected void write(String message); } //定義一個標(biāo)準(zhǔn)日志的實現(xiàn)類 public class ConsoleLogger extends AbstractLogger { public ConsoleLogger(int level){ this.level = level; } @Override protected void write(String message) { System.out.println("Standard Console::Logger: " + message); } } //定義一個錯誤日志的實現(xiàn)類 public class ErrorLogger extends AbstractLogger { public ErrorLogger(int level){ this.level = level; } @Override protected void write(String message) { System.out.println("Error Console::Logger: " + message); } } //定義一個文件日志的實現(xiàn)類 public class FileLogger extends AbstractLogger { public FileLogger(int level){ this.level = level; } @Override protected void write(String message) { System.out.println("File::Logger: " + message); } } //使用責(zé)任鏈模式 public class Client { //設(shè)置責(zé)任鏈的調(diào)用順序 private static AbstractLogger getChainOfLoggers(){ AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR); AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG); AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO); errorLogger.setNextLogger(fileLogger); fileLogger.setNextLogger(consoleLogger); return errorLogger; } public static void main(String[] args) { AbstractLogger loggerChain = getChainOfLoggers(); loggerChain.logMessage(AbstractLogger.INFO, "info level information."); loggerChain.logMessage(AbstractLogger.DEBUG, "debug level information."); loggerChain.logMessage(AbstractLogger.ERROR, "error information."); } }命令模式(Command Pattern)
命令模式是請求以命令的形式包裹在對象中,并傳給調(diào)用對象。調(diào)用對象尋找可以處理該命令的合適的對象,并把該命令傳給相應(yīng)的對象,該對象執(zhí)行命令。它屬于行為型模式。
它的優(yōu)點(diǎn):
1、降低了系統(tǒng)耦合度。
2、新的命令可以很容易添加到系統(tǒng)中去。
它的缺點(diǎn):
使用命令模式可能會導(dǎo)致某些系統(tǒng)有過多的具體命令類。
例如,我們用下面這個開關(guān)燈的例子來更好的理解命令模式。
// 定義執(zhí)行命令接口 public interface Command{ public void execute(); } //開燈命令實現(xiàn)類 public class LightOnCommand implements Command{ Light light; public LightOnCommand(Light light){ this.light = light; } public void execute(){ light.switchOn(); } } //關(guān)燈命令實現(xiàn)類 public class LightOffCommand implements Command{ Light light; public LightOffCommand(Light light){ this.light = light; } public void execute(){ light.switchOff(); } } //真正開關(guān)燈的類 public class Light{ private boolean on; public void switchOn(){ on = true; } public void switchOff(){ on = false; } } //根據(jù)不同命令執(zhí)行開關(guān)燈 public class RemoteControl{ private Command command; public void setCommand(Command command){ this.command = command; } public void pressButton(){ command.execute(); } } //調(diào)用命令模式 public class Client{ public static void main(String[] args){ RemoteControl control = new RemoteControl(); Light light = new Light(); Command lightsOn = new LightsOnCommand(light); Command lightsOff = new LightsOffCommand(light); //設(shè)置開燈命令來開燈 control.setCommand(lightsOn); control.pressButton(); //設(shè)置關(guān)燈命令來關(guān)燈 control.setCommand(lightsOff); control.pressButton(); } }解釋器模式(Interpreter Pattern)
解釋器模式是給定一種語言,定義其語法以及使用該語法來表示語言中句子的解釋器。這種模式實現(xiàn)了一個表達(dá)式接口,該接口解釋一個特定的上下文。這種模式被用在 SQL 解析、符號處理引擎等。它屬于行為型模式。
它的優(yōu)點(diǎn):
1、可擴(kuò)展性比較好,靈活。
2、增加了新的解釋表達(dá)式的方式。
3、易于實現(xiàn)簡單語法。
它的缺點(diǎn):
1、可利用場景比較少。
2、對于復(fù)雜的文法比較難維護(hù)。
3、解釋器模式會引起類膨脹。
4、解釋器模式采用遞歸調(diào)用方法。
例如,我們用下面這個簡單規(guī)則表達(dá)式的例子來更好的理解解釋器模式。
//定義一個表達(dá)式接口 public interface Expression { public boolean interpret(String context); } //定義一個基本規(guī)則的實現(xiàn),輸入的內(nèi)容包含初始化的內(nèi)容時,返回 true public class TerminalExpression implements Expression { private String data; public TerminalExpression(String data){ this.data = data; } @Override public boolean interpret(String context) { if(context.contains(data)){ return true; } return false; } } //定義一個或者規(guī)則的實現(xiàn),輸入的內(nèi)容包含初始化時任意一個內(nèi)容時,返回 true,否則 false public class OrExpression implements Expression { private Expression expr1 = null; private Expression expr2 = null; public OrExpression(Expression expr1, Expression expr2) { this.expr1 = expr1; this.expr2 = expr2; } @Override public boolean interpret(String context) { return expr1.interpret(context) || expr2.interpret(context); } } //定義一個并且規(guī)則的實現(xiàn),輸入的內(nèi)容同時包含初始化時兩個內(nèi)容時,返回 true,否則 false public class AndExpression implements Expression { private Expression expr1 = null; private Expression expr2 = null; public AndExpression(Expression expr1, Expression expr2) { this.expr1 = expr1; this.expr2 = expr2; } @Override public boolean interpret(String context) { return expr1.interpret(context) && expr2.interpret(context); } } //調(diào)用規(guī)則表達(dá)式 public class Client { //規(guī)則:Robert 和 John 是男性,輸入只要滿足其中一個規(guī)則就行 public static Expression getMaleExpression(){ Expression robert = new TerminalExpression("Robert"); Expression john = new TerminalExpression("John"); return new OrExpression(robert, john); } //規(guī)則:Julie 是一個已婚的女性,輸入只要滿足兩個規(guī)則 public static Expression getMarriedWomanExpression(){ Expression julie = new TerminalExpression("Julie"); Expression married = new TerminalExpression("Married"); return new AndExpression(julie, married); } public static void main(String[] args) { Expression isMale = getMaleExpression(); Expression isMarriedWoman = getMarriedWomanExpression(); System.out.println("John is male? " + isMale.interpret("John")); System.out.println("Julie is a married women? " + isMarriedWoman.interpret("Married Julie")); } }
最后,還是那句話,每種設(shè)計模式有它自己的好處,也有它的壞處。在寫代碼時,多思考,想好在寫,免得返工,先從思維方式上改變。使用單一原則,一個類,一個方法只做一件事情,這樣方便維護(hù),耦合低,可擴(kuò)展。
PS:
清山綠水始于塵,博學(xué)多識貴于勤。
微信公眾號:「清塵閑聊」。
歡迎一起談天說地,聊代碼。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/74942.html
摘要:維基百科抽象工廠的例子構(gòu)建模式當(dāng)構(gòu)建一個復(fù)雜對象時,就可以使用建造者模式。在中,類中的方法就是適配器模式的例子,把一個數(shù)組轉(zhuǎn)換為一個集合。這種設(shè)計模式的好處是方便添加一種車巴士,只需要繼承類。 寫在前面 評判一個程序員是否優(yōu)秀,就是 show me the code。優(yōu)秀的代碼可讀性強(qiáng),高內(nèi)聚低耦合,可擴(kuò)展。想要寫優(yōu)秀的代碼,做個優(yōu)秀的程序員,就需要多看看大牛寫的開源框架,吸取其中的精...
摘要:全書分三大部分共章第章介紹的基礎(chǔ)知識安裝和基本語法第章介紹的基本編程機(jī)器學(xué)習(xí)基礎(chǔ)及中常用的第三方庫函數(shù),并介紹數(shù)據(jù)預(yù)處理的基本方法第章分別介紹常用的機(jī)器學(xué)習(xí)分析算法及深度學(xué)習(xí)等。每章都采用多個經(jīng)典案例圖文并茂地介紹機(jī)器學(xué)習(xí)的原理和實現(xiàn)方法。 最近在學(xué)習(xí)Java和全棧開發(fā),推薦一些有用的書籍 書架主要針對Java后端和全棧開發(fā)用的 書籍介紹 《Spring Boot 2.0企業(yè)級應(yīng)用開發(fā)...
摘要:全書分三大部分共章第章介紹的基礎(chǔ)知識安裝和基本語法第章介紹的基本編程機(jī)器學(xué)習(xí)基礎(chǔ)及中常用的第三方庫函數(shù),并介紹數(shù)據(jù)預(yù)處理的基本方法第章分別介紹常用的機(jī)器學(xué)習(xí)分析算法及深度學(xué)習(xí)等。每章都采用多個經(jīng)典案例圖文并茂地介紹機(jī)器學(xué)習(xí)的原理和實現(xiàn)方法。 最近在學(xué)習(xí)Java和全棧開發(fā),推薦一些有用的書籍 書架主要針對Java后端和全棧開發(fā)用的 書籍介紹 《Spring Boot 2.0企業(yè)級應(yīng)用開發(fā)...
摘要:是一款基于的服務(wù)端渲染框架,跟的異曲同工。該配置項用于定義應(yīng)用客戶端和服務(wù)端的環(huán)境變量。 Vue因其簡單易懂的API、高效的數(shù)據(jù)綁定和靈活的組件系統(tǒng),受到很多前端開發(fā)人員的青睞。國內(nèi)很多公司都在使用vue進(jìn)行項目開發(fā),我們正在使用的簡書,便是基于Vue來構(gòu)建的。 我們知道,SPA前端渲染存在兩大痛點(diǎn):(1)SEO。搜索引擎爬蟲難以抓取客戶端渲染的頁面meta信息和其他SEO相關(guān)信息,使...
閱讀 1110·2021-10-14 09:43
閱讀 1159·2021-10-11 11:07
閱讀 3118·2021-08-18 10:23
閱讀 1495·2019-08-29 16:18
閱讀 1010·2019-08-28 18:21
閱讀 1481·2019-08-26 12:12
閱讀 3767·2019-08-26 10:11
閱讀 2508·2019-08-23 18:04