第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

首頁 慕課教程 Lambda 表達(dá)式教程 Lambda 表達(dá)式教程 Lambda 表達(dá)式修改設(shè)計(jì)模式

Lambda 表達(dá)式修改設(shè)計(jì)模式

本節(jié)內(nèi)容并不是討論設(shè)計(jì)模式,而是討論如何使用 Lambda 表達(dá)式讓現(xiàn)有的設(shè)計(jì)模式變得更簡潔,或者在某些情況是有一些不同的實(shí)現(xiàn)方式。我們可以從另一個(gè)角度來學(xué)習(xí)使用和理解 Lambda 表達(dá)式。

Tips: 要更好地理解本節(jié)內(nèi)容需要對(duì)涉及的四個(gè)設(shè)計(jì)模式有一定的了解,具體可以查閱相關(guān)資料。

1. 命令者模式

命令者模式是將操作、方法調(diào)用、命令封裝成一個(gè)對(duì)象,在合適的時(shí)候讓該對(duì)象進(jìn)行執(zhí)行。

它包五個(gè)角色:

  • 客戶端(Client):發(fā)出命令;
  • 調(diào)用者(Invoker):調(diào)用抽象命令,還可以記錄執(zhí)行的命令;
  • 接受者(Receiver):命令的實(shí)際執(zhí)行者,一個(gè)命令會(huì)存在一個(gè)或多個(gè)接收者;
  • 抽象命令(Command):定義命令執(zhí)行方法;
  • 具體命令(Concrete Command):調(diào)用接收者,執(zhí)行命令的具體方法。

命令者模式被大量運(yùn)用在組件化的圖形界面系統(tǒng)、撤銷功能、線城市、事務(wù)和向?qū)е小N覀儊砜匆粋€(gè)例子,我們實(shí)現(xiàn)一個(gè)將一系列命令錄制下來的功能,有點(diǎn)類似于 Word 中的撤銷功能那樣記錄每一步的操作。

//定義一個(gè)命令接收者,包含打開、關(guān)閉和保存三個(gè)操作  
public class Editor{  
	public void save(){  
		System.out.println("do save")  
	}  
	public void open();  
	public void close();  
}  
?  
// 定名命令對(duì)象,所有操作都要實(shí)現(xiàn)這個(gè)接口  
public interface Action{  
	public void perform();  
}  
?  
//實(shí)現(xiàn)保存命令操作  
public Save implements Action{  
	private final Editor editor;  
	    
	public Save(Editor editor){  
		this.editor = editor;  
	}  
	   
	public void perform(){  
		editor.save();  
	}  
}  
?  
//實(shí)現(xiàn)打開命令操作  
public class Open implements Action{  
	private final Editor editor;  
	?  
	public Open(Editor editor){  
		this.editor = editor;  
	}  
	public void perform(){  
		editor.open();  
	}  
}  
?  
//實(shí)現(xiàn)關(guān)閉命令操作  
public class Close implements Action{  
	private final Editor editor;  
	?  
	public Close(Editor editor){  
		this.editor = editor;  
	}  
	public void perform(){  
		editor.close();  
	}  
}  
?  
//定義命令發(fā)起者來記錄和順序執(zhí)行命令  
public class Invoker{  
	private final List<Action> actions = new ArrayList<>();  
	?  
	public void record(Action action){  
		actions.add(action);  
	}  
	public void run(){  
		for (Action action : actions) {  
			action.perform();  
		}  
	}  
}  
?  
//定義客戶端,用來記錄和執(zhí)行命令  
public class Client{  
	public static void main(String...s){  
		Invoker invoker = new Invoker();  
		Editor editor = new Editor();  
		//記錄保存操作  
		invoker.record(new Save(editor));  
		//記錄打開操作  
		invoker.record(new Open(editor));  
		//記錄關(guān)閉操作  
		invoker.record(new Close(editor));  
		invoker.run();  
	}  
}
輸出結(jié)果:

do save  
do open  
do close

以上是一個(gè)完整的命令者模式的例子,我們使用 Lambda 表達(dá)式來修改客戶端:

public class Client{  
	public static void main(String...s){  
		Invoker invoker = new Invoker();  
		Editor editor = new Editor();  
		//記錄保存操作  
		invoker.record(()->editor.open());  
		//記錄打開操作  
		invoker.record(()->editor.save());  
		//記錄關(guān)閉操作  
		invoker.record(()->editor.close());  
		invoker.run();  
	}  
}

我們使用引用方法來修改客戶端:

public class Client{  
	public static void main(String...s){  
		Invoker invoker = new Invoker();  
		Editor editor = new Editor();  
		//記錄保存操作  
		invoker.record(editor::open);  
		//記錄打開操作  
		invoker.record(editor::save);  
		//記錄關(guān)閉操作  
		invoker.record(editor::close);  
		invoker.run();  
	}  
}

通過這樣的改造,我們的代碼意圖更加明顯了呢,一看就明白具體記錄的是哪個(gè)操作。

2. 策略模式

策略模式是軟件運(yùn)行時(shí),根據(jù)實(shí)際情況改變軟件的算法行為。

常見的策略模式就是文件壓縮軟件,通常一個(gè)壓縮軟件可以支持多種壓縮算法如 zip 、gzip、rar 等,通過策略模式可以讓壓縮軟件根據(jù)我們具體的操作來實(shí)現(xiàn)不同的壓縮算法。我們來看一個(gè)壓縮數(shù)據(jù)的策略模式的例子:

//定義壓縮策略接口  
public interface CompressionStrategy{  
	public OutputStream compress(OutputStream data) throws IOException;  
}  
    
//gzip壓縮策略  
public class GzipStrategy implements CompressionStrategy{  
	@Override  
	public OutputStream compress(OutputStream data) throws IOException {  
		return new GZIPOutputStream(data);  
	}  
}  
    
//zip壓縮策略  
public class ZipStrategy implements  CompressionStrategy{  
	@Override  
	public OutputStream compress(OutputStream data) throws IOException {  
		return new ZipOutputStream(data);  
	}  
}  
?  
//在構(gòu)造類時(shí)提供壓縮策略  
public class Compressor{  
	private final CompressionStrategy strategy;  
	public Compressor(CompressionStrategy strategy){  
		this.strategy = strategy;  
	}  
	public void compress(Path inFiles, File outputFile) throws IOException{  
		try(OutputStream outputStream = new FileOutputStream(outputFile)){  
			Files.copy(inFiles,strategy.compress(outputStream));  
		}  
	}  
}  
//使用具體的策略初始化壓縮策略  
//gzip策略  
Compressor gzipCompressor = new Compressor(new GzipStrategy());  
//zip策略  
Compressor zipCompressor = new Compressor(new ZipStrategy());

以上就是一個(gè)完整的 zip 和 gzip 的壓縮策略?,F(xiàn)在我們用 Lambda 表達(dá)式來優(yōu)化初始化壓縮策略

//使用構(gòu)造器引用優(yōu)化初始化壓縮策略  
//gzip策略  
Compressor gzipCompressor = new Compressor(GzipStrategy::new);  
//zip策略  
Compressor zipCompressor = new Compressor(ZipStrategy::new);

3. 觀察者模式

觀察者模式是定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新。

觀察者模式被適用于消息通知、觸發(fā)器之類的應(yīng)用場景中

觀察者模式包含三個(gè)類 主題(Subject)、觀察者(Observer)和客戶端(Client)。Subject 對(duì)象帶有綁定觀察者到 Client 對(duì)象和從 Client 對(duì)象解綁觀察者的方法。

我們來看一個(gè)例子:現(xiàn)在我們用觀察者模式實(shí)現(xiàn)根據(jù)輸入的數(shù)字,自動(dòng)將輸入的數(shù)字其轉(zhuǎn)變成對(duì)應(yīng)十六進(jìn)制和二進(jìn)制。

//定義一個(gè)觀察者  
public interface Observer {  
	public  void update(int num);  
}  
?  
//創(chuàng)建主題  
public static class Subject{  
	private List<Observer> observers = new ArrayList<>();  
	private int num;  
	public int getNum(){  
		return num;  
	}  
	private void setNum(int num){  
		this.num = num;  
		this.notifyAllObservers();  
	}  
private void addObserver(Observer observer) {  
	observers.add(observer);  
}  
?  
	private void notifyAllObservers(){  
		for(Observer observer:observers){  
			observer.update(num);  
		}  
	}  
}  
?  
//創(chuàng)建二進(jìn)制觀察者  
public static class BinaryObserver implements Observer{  
?  
	private Subject subject;  
	?  
	?  
	@Override  
	public void update(int num) {  
		System.out.println( "Binary String: "  
					+ Integer.toBinaryString( num ) );  
		}  
}  
?  
//創(chuàng)建十六進(jìn)制觀察者  
public static class HexObserver implements Observer{  
?  
	@Override  
	public void update(int num) {  
		System.out.println( "Hex String: "  
					+ Integer.toHexString( num ) );  
	}  
}  
?  
//使用 Subject 和實(shí)體觀察者對(duì)象  
public class Demo{  
	public static void main(String... s){  
		Subject subject = new Subject();  
		subject.addObserver(new BinaryObserver());  
		subject.addObserver(new HexObserver());  
		System.out.println("first input is:11");  
		subject.setNum(11);  
		System.out.println("second input is:15");  
		subject.setNum(15);  
	}  
}  
輸出結(jié)果:

first input is:11  
Binary String: 1011  
Hex String: b  
second input is:15  
Binary String: 1111  
Hex String: f

同樣我們使用 Lambda 表達(dá)式來修改 Demo 類:

public class Demo{  
	public static void main(String...s){  
		Subject subject = new Subject();  
		subject.addObserver( num -> System.out.println( "Binary String: " + Integer.toBinaryString( num )));  
		subject.addObserver( num -> System.out.println( "Hex String: " + Integer.toHexString(num )));  
		System.out.println("first input is:11");  
		subject.setNum(11);  
		System.out.println("second input is:15");  
		subject.setNum(15);  
	}  
}

在這個(gè)例子中,我們實(shí)際上是省去了 BinaryObserverHexObserver 兩個(gè)類的定義,直接使用 Lambda 表達(dá)式來描述二進(jìn)制和十六進(jìn)制轉(zhuǎn)化的邏輯。

4. 模板方法模式

模板方法模式是定義一個(gè)操作中的算法的骨架,從而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。

通常對(duì)于一些重要的復(fù)雜方法和多個(gè)子類共有的方法且邏輯相同的情況下會(huì)使用模板方法模式。比如用戶第三方用戶認(rèn)證的時(shí)候就比較適合使用模板方法。

我們來看一個(gè)例子:假設(shè)我們現(xiàn)在需要用到微信、微博的第三方用戶授權(quán)來獲取用戶的信息。

//使用模板方法模式描述獲取第三方用戶信息的過程  
public abstract class Authentication{  
	public void checkUserAuthentication(){  
		checkIdentity();  
		fetchInfo();  
	}  
?  
	protected abstract void checkIdentity();  
	protected abstract void fetchInfo();  
}  
?  
//微信用戶  
public class WechatAuthenication extends Authentication{  
	@Override  
	protected void checkIdentity() {  
		System.out.println("獲得微信用戶授權(quán)");  
	}  
?  
	@Override  
	protected void fetchInfo() {  
		System.out.println("獲取微信用信息");  
	}  
}  
?  
//微信用戶  
public class WeiboAuthenication extends Authentication{  
	@Override  
	protected void checkIdentity() {  
		System.out.println("獲得微博用戶授權(quán)");  
	}  
?  
	@Override  
	protected void fetchInfo() {  
		System.out.println("獲取微博用信息");  
	}  
}  
?  
//調(diào)用模板方法  
public class Demo{  
	public static void main(String...s){  
		Authentication auth = new WechatAuthenication();  
		auth.checkUserAuthentication();  
		auth = new WeiboAuthenication();  
		auth.checkUserAuthentication();  
	}  
}
輸出結(jié)果:

獲得微信用戶授權(quán)  
獲取微信用信信息  
獲得微博用戶授權(quán)  
獲取微博用信信息

現(xiàn)在我們使用 Lambda 表達(dá)式換個(gè)角度來思考模板方法模式。如果我們用函數(shù)式接口來組織模板方法中的調(diào)用過程,相比使用繼承來構(gòu)建要顯得靈活的多。

//定義一個(gè)處理接口,用來處理一項(xiàng)事務(wù),如授權(quán)或者獲取信息。  
public interface Processer{  
	public void process();  
}  
?  
//封裝調(diào)用過程  
public class Authentication{  
	private final Processer identity;  
	private final Processer userinfo;  
	
	public Authentication(Criteria identity,Criteria userinfo){  
		this.identity = identity;  
		this.userinfo = userinfo;  
	}  
?  
	public void checkUserAuthentication(){  
		identity.process();  
		userinfo.process();  
	}  
}  
?  
//使用模板方法  
public class Demo{  
	Authentication auth = new Authentication(()->System.out.println("獲得微信用戶授權(quán)"),  
				()->System.out.println("獲取微信用戶信息"));  
	auth.checkUserAuthentication();  
	auth = new Authentication(()->System.out.println("獲得微博用戶授權(quán)"),  
				()->System.out.println("獲取微博用戶信息"));  
	auth.checkUserAuthentication();  
}
輸出結(jié)果:

獲得微信用戶授權(quán)  
獲取微信用信信息  
獲得微博用戶授權(quán)  
獲取微博用信信息

此時(shí),我們的模板方法得到了大幅的簡化,同時(shí)通過函數(shù)接口讓模板方法獲得了極大的靈活性。

5. 小結(jié)

圖片描述

本節(jié)我們討論如何使用 Lambda 表達(dá)式讓我們的設(shè)計(jì)模式變得更簡單、更好用。這里我們使用了四個(gè)例子從不同的角度來。

  • 命令者模式:我們使用 Lamabda 表達(dá)式的方法引用來進(jìn)行改造;
  • 策略模式:我們使用了 Lambda 表達(dá)式的構(gòu)造器引用來進(jìn)行改造;
  • 觀察者模式:我們使用了標(biāo)準(zhǔn)的 Lambda 表達(dá)式來進(jìn)行改造;
  • 模板方法模式:我們使用了函數(shù)式接口來進(jìn)行改造。

目的是希望給大家一點(diǎn)啟發(fā),在平常的編碼過程中去思考如何使用 Lambda 表達(dá)式來設(shè)計(jì)我們的程序。對(duì)于其他的設(shè)計(jì)模式如果感興趣的話可以自己嘗試下去修改它們。