很可惜 T 。T 您現(xiàn)在還不是作者身份,不能自主發(fā)稿哦~
如有投稿需求,請(qǐng)把文章發(fā)送到郵箱tougao@appcpx.com,一經(jīng)錄用會(huì)有專人和您聯(lián)系
咨詢?nèi)绾纬蔀榇河鹱髡哒?qǐng)聯(lián)系:鳥(niǎo)哥筆記小羽毛(ngbjxym)
publicvoiddosomething(Stringcommond){publicvoiddosomething(Stringcommond){publicvoiddosomething(Stringcommond){
1. 什么是代理模1式
抽象點(diǎn)說(shuō)是一個(gè)類代表另一個(gè)類的功能,或者說(shuō)一個(gè)對(duì)象為另一個(gè)對(duì)象提供一個(gè)代理或者占位符以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。同樣我也會(huì)舉例子來(lái)說(shuō)明,這里我舉一個(gè)買車票的例子。通常我們我們買車票需要去車站買,但是這樣會(huì)很麻煩,可能要坐很久的車去車站,然后在排隊(duì)買票。但是如果我們?nèi)ヒ粋€(gè)賣車票的代理點(diǎn)買車票可能就會(huì)省去這么多的事情。這樣車票售賣處就代理你購(gòu)買車票。
2. 代理模式結(jié)構(gòu)
3. 應(yīng)用
下面我們就用具體的代碼來(lái)實(shí)現(xiàn)上面這個(gè)買車票的靜態(tài)代理。
首先創(chuàng)建一個(gè)售票服務(wù)的接口,它有售票咨詢和退票的業(yè)務(wù)可以供客戶選擇。
public interface TicketService { //售票 void sellTicket(); //咨詢 void Consultation(); //退票 void ReturnTicket(); }
然后創(chuàng)建一個(gè)售票服務(wù)接口實(shí)現(xiàn)類,就好比是車站。
public class Station implements TicketService { @Override public void sellTicket() { System.out.println("售票"); } @Override public void Consultation() { System.out.println("咨詢"); } @Override public void ReturnTicket() { System.out.println("退票"); } }
然后創(chuàng)建一個(gè)代理售票點(diǎn)
public class StationProxy implements TicketService { private Station station; public StationProxy(Station station){ this.station = station; } @Override public void sellTicket() { System.out.println("歡迎使用車票代售點(diǎn)進(jìn)行購(gòu)票,每張票將會(huì)收取5元手續(xù)費(fèi)!"); station.sellTicket(); System.out.println("歡迎下次光臨"); } @Override public void Consultation() { System.out.println("歡迎咨詢,咨詢不收取費(fèi)用"); station.Consultation(); System.out.println("歡迎下次光臨"); } @Override public void ReturnTicket() { System.out.println("歡迎使用車票代售點(diǎn)進(jìn)行退票,每張票將會(huì)收取5元手續(xù)費(fèi)!"); station.ReturnTicket(); System.out.println("歡迎下次光臨"); } }
創(chuàng)建購(gòu)買車票的角色,去代理點(diǎn)完成購(gòu)買車票的需求
public class ProxyTest { public static void main(String[] args) { Station station = new Station(); StationProxy stationProxy = new StationProxy(station); stationProxy.sellTicket(); } }
可以看到這個(gè)購(gòu)買車票的客戶是去的車票代理點(diǎn),直接購(gòu)買車票,那代理點(diǎn)能否幫助他正常購(gòu)買到車票呢?請(qǐng)看下面的執(zhí)行結(jié)果
從結(jié)果看到售票代理點(diǎn)成功幫助客戶購(gòu)買到車票,節(jié)省了客戶去車站排隊(duì)等待的時(shí)間和精力。代理模式有點(diǎn)像是委派模式中的中介,前面的文章也提到過(guò)靜態(tài)代理和策略模式是委派模式的一種組合。那當(dāng)然除了靜態(tài)代理還有動(dòng)態(tài)代理和CGLIB代理,感興趣的伙伴可以自己去研究研究。
1. 什么是工廠模式
老規(guī)矩先用比較難理解的官方語(yǔ)言來(lái)表達(dá),工廠模式是 Java 中最常用的設(shè)計(jì)模式之一。這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的最佳方式。在工廠模式中,我們?cè)趧?chuàng)建對(duì)象時(shí)不會(huì)對(duì)客戶端暴露創(chuàng)建邏輯,并且是通過(guò)使用一個(gè)共同的接口來(lái)指向新創(chuàng)建的對(duì)象。現(xiàn)在在以一個(gè)具體的例子來(lái)簡(jiǎn)單簡(jiǎn)化下工廠模式。假如我現(xiàn)在去餐館吃飯,餐館有回鍋肉,有魚(yú),有烤鴨可供我選擇,然后我點(diǎn)餐餐館為我做出具體的菜。說(shuō)完這個(gè)例子下面我也會(huì)用代碼來(lái)實(shí)現(xiàn)這個(gè)例子,給大家簡(jiǎn)單理解下工廠模式。
首先我們來(lái)創(chuàng)建一個(gè)餐館的接口,因?yàn)檫@里只要有做菜就行,所以寫(xiě)一個(gè)cook的方法。
public interface Resaurant { void cook(); }
接下來(lái)寫(xiě)三個(gè)實(shí)現(xiàn)類,分別是做回鍋肉的,做魚(yú)的,做烤鴨的,用這三個(gè)實(shí)現(xiàn)類去實(shí)現(xiàn)餐館的接口。
public class Duck implements Resaurant{ public void cook() { System.out.println("來(lái)一份烤鴨"); } }
public class Fish implements Resaurant{ public void cook() { System.out.println("來(lái)一份紅燒魚(yú)"); } }
public class Meet implements Resaurant { public void cook() { System.out.println("來(lái)一份回鍋肉"); } }
現(xiàn)在餐館已經(jīng)具備了做回鍋肉,做魚(yú),做烤鴨的功能,但是客人來(lái)了并不知道餐館有這些菜,這時(shí)候就需要我們來(lái)給餐館做一個(gè)菜單,客人來(lái)了就可以根據(jù)菜單點(diǎn)餐,這樣就省去了很多的麻煩對(duì)不對(duì)?
public class Wait { public static final int MEAN_MEET = 1; public static final int MEAN_FISH = 2; public static final int MEAN_DUCK = 3; public static Resaurant getMean(int meantype){ switch (meantype){ case MEAN_MEET : return new Meet(); case MEAN_FISH : return new Fish(); case MEAN_DUCK : return new Duck(); default: return null; } } }
菜單也有了,現(xiàn)在客人來(lái)了可以點(diǎn)餐了,假如客人根據(jù)菜單點(diǎn)了一份烤鴨,那餐館就可以直接給客人制作一份美味的烤鴨
public class Factory { public static void main(String[] args) { //簡(jiǎn)單工廠模式 Resaurant resaurant = Wait.getMean(Wait.MEAN_DUCK); resaurant.cook(); } }
來(lái)看看執(zhí)行結(jié)果
通過(guò)上面的例子就給大家簡(jiǎn)單介紹了一下簡(jiǎn)單工廠模式。但是工廠模式除了簡(jiǎn)單工廠模式還有工廠方法模式和抽象工廠模式,下面我再已餐館這個(gè)例子給大家擴(kuò)展一下工廠方法模式。工廠方法模式就是把簡(jiǎn)單工廠中具體的工廠類,劃分成兩層:抽象工廠層+具體的工廠子類層。
首先我們來(lái)創(chuàng)建一個(gè)抽象工廠類
public abstract class CookFactory { public abstract Resaurant createRestaurant(); }
創(chuàng)建兩個(gè)具體需要的產(chǎn)品實(shí)現(xiàn)類去繼承上面這個(gè)抽象類
public class DuckFactory extends CookFactory { @Override public Resaurant createRestaurant() { return new Duck(); } }
public class FishFactory extends CookFactory { public Resaurant createRestaurant() { return new Fish(); } }
烤鴨和魚(yú)都做好了,開(kāi)始享用吧!
public class Cook { //工廠方法模式 public static void main(String[] args) { Resaurant duck = new DuckFactory().createRestaurant(); duck.cook(); Resaurant fish = new FishFactory().createRestaurant(); fish.cook(); } }
看下執(zhí)行結(jié)果
千呼萬(wàn)喚始出來(lái),紅燒魚(yú)和烤鴨出鍋咯!
2. 優(yōu)點(diǎn)和缺點(diǎn)
優(yōu)點(diǎn):
缺點(diǎn):每次增加一個(gè)產(chǎn)品時(shí),都需要增加一個(gè)具體類和對(duì)象實(shí)現(xiàn)工廠,使得系統(tǒng)中類的個(gè)數(shù)成倍增加,在一定程度上增加了系統(tǒng)的復(fù)雜度,同時(shí)也增加了系統(tǒng)具體類的依賴。這并不是什么好事。
1. 單例模式
所謂單例,通俗來(lái)說(shuō),就是天上只能有一個(gè)太陽(yáng),只能有一個(gè)月亮,所以結(jié)合到代碼中,就是我們不能每次創(chuàng)建對(duì)象都new一個(gè)新
的對(duì)象供我們使用。所以這個(gè)對(duì)象應(yīng)該被設(shè)計(jì)為共享對(duì)象,當(dāng)需要?jiǎng)?chuàng)建時(shí),只需把這個(gè)共享對(duì)象的引用賦值給變量即可。所謂共享,
即對(duì)象被為static object,且共享對(duì)象參數(shù)改變時(shí),應(yīng)考慮對(duì)其他使用對(duì)象的影響,一般不輕易改變共享對(duì)象的內(nèi)容。
設(shè)計(jì)單例方式并不唯一,應(yīng)該考慮線程安全、效率等,根據(jù)自己的業(yè)務(wù)需求來(lái)設(shè)計(jì)。下面展示簡(jiǎn)單的設(shè)計(jì)思想。
2. 單例模式的幾種實(shí)現(xiàn)方式
單例模式的實(shí)現(xiàn)有多種方式,如下所示:
①. 懶漢式,線程不安全
描述:這種方式是最基本的實(shí)現(xiàn)方式,這種實(shí)現(xiàn)最大的問(wèn)題就是不支持多線程。因?yàn)闆](méi)有加鎖 synchronized,所以嚴(yán)格意義上它并不算單例模式。 這種方式 lazy loading 很明顯,不要求線程安全,在多線程不能正常工作。
實(shí)例
public class Singleton { private static Singleton instance; private Singleton (){ } public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
②. 懶漢式,線程安全
描述:這種方式具備很好的 lazy loading,能夠在多線程中很好的工作,但是,效率很低,99% 情況下不需要同步。 優(yōu)點(diǎn):第一次調(diào)用才初始化,避免內(nèi)存浪費(fèi)。 缺點(diǎn):必須加鎖 synchronized 才能保證單例,但加鎖會(huì)影響效率。 getInstance() 的性能對(duì)應(yīng)用程序不是很關(guān)鍵(該方法使用不太頻繁)。
實(shí)例
public class Singleton { private static Singleton instance; private Singleton (){ } public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
③. 餓漢式
描述:這種方式比較常用,但容易產(chǎn)生垃圾對(duì)象。
優(yōu)點(diǎn):沒(méi)有加鎖,執(zhí)行效率會(huì)提高。
缺點(diǎn):類加載時(shí)就初始化,浪費(fèi)內(nèi)存。
它基于 classloader 機(jī)制避免了多線程的同步問(wèn)題,不過(guò),instance 在類裝載時(shí)就實(shí)例化,雖然導(dǎo)致類裝載的原因有很多種,在單例模式中大多數(shù)都是調(diào)用 getInstance 方法, 但是也不能確定有其他的方式(或者其他的靜態(tài)方法)導(dǎo)致類裝載,這時(shí)候初始化 instance 顯然沒(méi)有達(dá)到 lazy loading 的效果。
實(shí)例
public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){ } public static Singleton getInstance() { return instance; } }
④. 雙檢鎖/雙重校驗(yàn)鎖(DCL,即 double-checked locking) JDK 版本:JDK1.5 起
描述:這種方式采用雙鎖機(jī)制,安全且在多線程情況下能保持高性能。 getInstance() 的性能對(duì)應(yīng)用程序很關(guān)鍵。
實(shí)例
public class Singleton { private volatile static Singleton singleton; private Singleton (){ } public static Singleton getSingleton() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
⑤. 登記式/靜態(tài)內(nèi)部類
描述:這種方式能達(dá)到雙檢鎖方式一樣的功效,但實(shí)現(xiàn)更簡(jiǎn)單。對(duì)靜態(tài)域使用延遲初始化,應(yīng)使用這種方式而不是雙檢鎖方式。
這種方式只適用于靜態(tài)域的情況,雙檢鎖方式可在實(shí)例域需要延遲初始化時(shí)使用。
這種方式同樣利用了 classloader 機(jī)制來(lái)保證初始化 instance 時(shí)只有一個(gè)線程,它跟第 3 種方式不同的是:第 3 種方式只要
Singleton 類被裝載了,那么 instance 就會(huì)被實(shí)例化(沒(méi)有達(dá)到 lazy loading 效果),而這種方式是 Singleton 類被裝載了,instance 不一定被初始化。因?yàn)?SingletonHolder 類沒(méi)有被主動(dòng)使用,
只有通過(guò)顯式調(diào)用 getInstance 方法時(shí),才會(huì)顯式裝載 SingletonHolder 類,從而實(shí)例化 instance。想象一下,如果實(shí)例化 instance 很消耗資源,所以想讓它延遲加載,另外一方面,又不希望在 Singleton 類加載時(shí)就實(shí)例化,
因?yàn)椴荒艽_保 Singleton 類還可能在其他的地方被主動(dòng)使用從而被加載,那么這個(gè)時(shí)候?qū)嵗?instance 顯然是不合適的。這個(gè)時(shí)候,這種方式相比第 3 種方式就顯得很合理。
實(shí)例
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){ } public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
⑥. 枚舉 JDK 版本:JDK1.5 起
描述:這種實(shí)現(xiàn)方式還沒(méi)有被廣泛采用,但這是實(shí)現(xiàn)單例模式的最佳方法。它更簡(jiǎn)潔,自動(dòng)支持序列化機(jī)制,絕對(duì)防止多次實(shí)例化。
這種方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不僅能避免多線程同步問(wèn)題,而且還自動(dòng)支持序列化機(jī)制,
防止反序列化重新創(chuàng)建新的對(duì)象,絕對(duì)防止多次實(shí)例化。不過(guò),由于 JDK1.5 之后才加入 enum 特性,用這種方式寫(xiě)不免讓人感覺(jué)生疏,在實(shí)際工作中,也很少用。 不能通過(guò) reflection attack 來(lái)調(diào)用私有構(gòu)造方法。
實(shí)例
public enum Singleton { INSTANCE; public void whateverMethod() { } }
經(jīng)驗(yàn)之談:一般情況下,不建議使用第 1 種和第 2 種懶漢方式,建議使用第 3 種餓漢方式。只有在要明確實(shí)現(xiàn) lazy loading 效果
時(shí),才會(huì)使用第 5 種登記方式。如果涉及到反序列化創(chuàng)建對(duì)象時(shí),可以嘗試使用第 6 種枚舉方式。如果有其他特殊的需求,
可以考慮使用第 4 種雙檢鎖方式。
1. 什么是委派模式
這里我以一個(gè)簡(jiǎn)單的例子來(lái)形容,公司有大boss和部門(mén)leader以及部門(mén)里的員工,現(xiàn)在大boss給部門(mén)leader下達(dá)了任務(wù),而作為部門(mén)leader肯定是對(duì)任務(wù)進(jìn)行具體的規(guī)劃然后委派給部門(mén)里的員工去完成。這中間的關(guān)系就類似于委派模式。作為大boss他可以不知道任務(wù)具體是哪個(gè)員工做的,甚至可以不知道員工的存在,只要以結(jié)果為導(dǎo)向,最終能完成任務(wù)就可以。作為部門(mén)leader相當(dāng)于一個(gè)中介,全程跟進(jìn)員工的工作進(jìn)度,最終像大boss匯報(bào)工作。作為員工只要完成任務(wù)可以不知道任務(wù)最終是大boss 下達(dá)的。 接下來(lái)就以具體的代碼來(lái)實(shí)現(xiàn)這樣一個(gè)委派模式的關(guān)系
2. 創(chuàng)建一個(gè)員工干活的接口Target
public interface Target { public void dosomething(String commond); }
3. 創(chuàng)建兩個(gè)員工類ATarget和BTarget
用這兩個(gè)員工去實(shí)現(xiàn)干活的接口,但是現(xiàn)在員工還不知道他具體需要干什么,因?yàn)槭遣块T(mén)leader給他們分配任務(wù)。
A員工的工作類
public class ATarget implements Target { //A員工做具體的事情 @Override public void dosomething(String commond) { System.out.println("A員工做具體的事情"+commond + ""); } }
B員工工作類
public class BTarget implements Target { //B員工需要做的事情 @Override public void dosomething(String commond) { System.out.println("B員工做具體的事情"+commond); } }
創(chuàng)建一個(gè)部門(mén)leader的類去實(shí)現(xiàn)Target,用這個(gè)leader去給員工分配具體的工作任務(wù)。
public class Leader implements Target { //領(lǐng)導(dǎo)委派員工做具體的事情 private Maptarget = new HashMap (); public Leader(){ //領(lǐng)導(dǎo)委派員工A和員工B分別做不同的事情 target.put("打印文件", new ATarget()); target.put("測(cè)試項(xiàng)目", new BTarget()); } @Override public void dosomething(String commond) { target.get(commond).dosomething(commond); } }
接下來(lái)就是大boss上場(chǎng),但是大boss不會(huì)去直接給做事的員工下達(dá)命令,而是給leader直接下達(dá)命令,比如下達(dá)一個(gè)打印文件的工作。
public class DelegateTest { public static void main(String[] args) { new Leader().dosomething("打印文件"); } }
可以看出來(lái)部門(mén)leader類是一個(gè)至關(guān)重要的類,起到了承上啟下的中介作用,這就是一個(gè)委派。然后我們來(lái)運(yùn)行程序,來(lái)看看大boss沒(méi)有給員工直接下達(dá)工作命令,員工能否完成任務(wù)。
可以清楚的看出A員工完成了大boss交給的打印文件的任務(wù)(順利完成任務(wù),可以去申請(qǐng)加薪了)
從上面可以看出來(lái)委派模式就是靜態(tài)代理和策略模式的一種特殊組合,代理模式注重的是過(guò)程,委派模式注重的是結(jié)果。策略模式注重的是可擴(kuò)展(外部擴(kuò)展),委派模式注重的是內(nèi)部的靈活和復(fù)用(委派模式以結(jié)果為導(dǎo)向)。
1. 策略模式
策略模式定義了一系列的算法,并將每一個(gè)算法封裝起來(lái),而且使他們之間可以相互替換,策略模式可以在不影響客戶端的情況下發(fā)生變化。 策略模式是處理算法不同變體的一種成熟模式,策略模式通過(guò)接口或抽象類封裝算法的標(biāo)識(shí),即在接口中定義一個(gè)抽象方法,實(shí)現(xiàn)該接口的類將實(shí)現(xiàn)接口中的抽象方法。策略模式把針對(duì)一個(gè)算法標(biāo)識(shí)的一系列具體算法分別封裝在不同的類中,使得各個(gè)類給出的具體算法可以相互替換。
策略模式的結(jié)構(gòu):
2. 舉例
假如某個(gè)游樂(lè)場(chǎng)有幾種購(gòu)買門(mén)票的方式,普通的游客是不能享受優(yōu)惠,經(jīng)常來(lái)的游客可以辦理年卡享受8折優(yōu)惠,當(dāng)然對(duì)于身高在1米2以下的兒童給與了5折的優(yōu)惠。這是游樂(lè)場(chǎng)的一種營(yíng)銷策略。對(duì)于這三種營(yíng)銷策略我們可以使用if else的語(yǔ)句在一個(gè)類中就能實(shí)現(xiàn),可是對(duì)于后續(xù)的維護(hù)可能就有其他的麻煩的地方了。如果后面又有更多的優(yōu)惠策略難道我們就不停的加 else語(yǔ)句嗎?這樣就會(huì)造成代碼看上去很復(fù)雜,且不容易維護(hù)。說(shuō)了這些策略模式就可以解決這樣的問(wèn)題。
3. 實(shí)戰(zhàn)
創(chuàng)建一個(gè)策略角色的接口,很簡(jiǎn)單的一個(gè)接口,寫(xiě)一個(gè)買票的方法。
public interface TicketStrategy { void BuyTicket(); }
接下來(lái)創(chuàng)建三個(gè)具體策略類,對(duì)應(yīng)的就是三種購(gòu)票的方式。
普通的游客購(gòu)票
public class Normal implements TicketStrategy { @Override public void BuyTicket() { System.out.println("普通游客沒(méi)有優(yōu)惠"); } }
辦理年卡的用戶購(gòu)票
public class Vip implements TicketStrategy { @Override public void BuyTicket() { System.out.println("辦年卡游客享受8折優(yōu)惠"); } }
1米2以下兒童購(gòu)票
public class Children implements TicketStrategy { @Override public void BuyTicket() { System.out.println("1米2以下兒童享受5折優(yōu)惠"); } }
創(chuàng)建上下文類。
public class Context { private TicketStrategy ticketStrategy; public Context(TicketStrategy strategy){ this.ticketStrategy = strategy; } public void setTicketStrategy(TicketStrategy ticketStrategy) { this.ticketStrategy = ticketStrategy; } public void BuyTicket(){ this.ticketStrategy.BuyTicket(); } }
4. 測(cè)試
public class StrategyTest { public static void main(String[] args) { System.out.println("普通游客策略:"); Context context = new Context(new Normal()); context.BuyTicket(); System.out.println("年卡VIP游客策略:"); context.setTicketStrategy(new Vip()); context.BuyTicket(); System.out.println("1米2以下兒童策略:"); context.setTicketStrategy(new Children()); context.BuyTicket(); } }
通過(guò)上面的例子可以看出這樣寫(xiě)就能讓代碼很簡(jiǎn)潔明了。后面如果有新的售票方式我們只需要?jiǎng)?chuàng)建具體策略類,然后調(diào)用就好了。
5. 優(yōu)點(diǎn)和缺點(diǎn)
優(yōu)點(diǎn):
缺點(diǎn):通過(guò)上面Demo我們會(huì)發(fā)現(xiàn)調(diào)用者必須知道所有的策略類,并自行決定使用哪一個(gè)策略類。這就意味著客戶端必須理解這些算法的區(qū)別,以便適時(shí)選擇恰當(dāng)?shù)乃惴惒⑶矣捎诓呗阅J桨衙總€(gè)具體的策略實(shí)現(xiàn)都單獨(dú)封裝成為類,如果備選的策略很多的話,那么對(duì)象的數(shù)目就會(huì)很可觀。
1. 原型模式
原型模式是用于創(chuàng)建重復(fù)的對(duì)象,同時(shí)又能保證性能。這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的最佳方式。這種模式是實(shí)現(xiàn)了一個(gè)原型接口,該接口用于創(chuàng)建當(dāng)前對(duì)象的克隆。當(dāng)直接創(chuàng)建對(duì)象的代價(jià)比較大時(shí),則采用這種模式。例如,一個(gè)對(duì)象需要在一個(gè)高代價(jià)的數(shù)據(jù)庫(kù)操作之后被創(chuàng)建。我們可以緩存該對(duì)象,在下一個(gè)請(qǐng)求時(shí)返回它的克隆,在需要的時(shí)候更新數(shù)據(jù)庫(kù),以此來(lái)減少數(shù)據(jù)庫(kù)調(diào)用。 現(xiàn)在我們就用原型模式來(lái)模擬復(fù)制東西,來(lái)復(fù)制一份個(gè)人簡(jiǎn)歷。
下面就是某某的求職簡(jiǎn)歷
public class Resume implements Cloneable { private String name; private String birthday; private String sex; private String school; private String timearea; private String company; public Resume(String name) { this.name = name; } /** * @desc 設(shè)定個(gè)人基本信息 * @param birthday 生日 * @param sex 性別 * @param school 畢業(yè)學(xué)校 * @return void */ public void setPersonInfo(String birthday,String sex,String school){ this.birthday = birthday; this.sex = sex; this.school = school; } /** * @desc 設(shè)定工作經(jīng)歷 * @param timearea 工作年限 * @param company 所在公司 * @return void */ public void setWorkExperience(String timearea,String company){ this.timearea = timearea; this.company = company; } /** * 克隆該實(shí)例 */ public Object clone(){ Resume resume = null; try { resume = (Resume) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return resume; } public void display(){ System.out.println("姓名:" + name); System.out.println("生日:" + birthday + ",性別:" + sex + ",畢業(yè)學(xué)校:" + school); System.out.println("工作年限:" + timearea + ",公司:" + company); } }
客戶端的驗(yàn)證測(cè)試操作
public static void main(String[] args) { //原型A對(duì)象 Resume a = new Resume("James"); a.setPersonInfo("2.16", "男", "家里蹲大學(xué)"); a.setWorkExperience("2018.09.05", "搬磚工地"); //克隆B對(duì)象 Resume b = (Resume) a.clone(); //輸出A和B對(duì)象 System.out.println("----------------A--------------"); a.display(); System.out.println("----------------B--------------"); b.display(); /* * 測(cè)試A==B? * 對(duì)任何的對(duì)象x,都有x.clone() !=x,即克隆對(duì)象與原對(duì)象不是同一個(gè)對(duì)象 */ System.out.print("A==B?"); System.out.println( a == b); /* * 對(duì)任何的對(duì)象x,都有x.clone().getClass()==x.getClass(),即克隆對(duì)象與原對(duì)象的類型一樣。 */ System.out.print("A.getClass()==B.getClass()?"); System.out.println(a.getClass() == b.getClass()); }
執(zhí)行結(jié)果
2. 總結(jié)
優(yōu)點(diǎn):
缺點(diǎn):
1. 模板模式
定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中。 模板方法使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。通俗的說(shuō)的就是有很多相同的步驟的,在某一些地方可能有一些差別適合于這種模式,如大話設(shè)計(jì)模式中說(shuō)到的考試場(chǎng)景中,每個(gè)人的試卷都是一樣的,只有答案不一樣。這種場(chǎng)景就適合于模板方法模式。我這次自己寫(xiě)的是一個(gè)汽車啟動(dòng)的過(guò)程,每一種汽車啟動(dòng)的過(guò)程都基本是一樣的流程,無(wú)非是這一過(guò)程中存在一些細(xì)小差別。 總的來(lái)說(shuō),模板模式就是通過(guò)抽象類來(lái)定義一個(gè)邏輯模板,邏輯框架、邏輯原型,然后將無(wú)法決定的部分抽象成抽象類交由子類來(lái)實(shí)現(xiàn),一般這些抽象類的調(diào)用邏輯還是在抽象類中完成的。這么看來(lái),模板就是定義一個(gè)框架,比如造車子,需要造車輪,車身,發(fā)動(dòng)機(jī),車燈等部分組成,不同的車的區(qū)別就在于這些部件的優(yōu)劣而已,但是總少不了這些東西。下面我就用一個(gè)例子來(lái)造一輛路虎越野車和一輛奧迪轎車。
2. 模板模式實(shí)戰(zhàn)
首先需要?jiǎng)?chuàng)建一個(gè)模板抽象父類,將造車需要的模塊創(chuàng)建好。
public abstract class CarTemplate { protected String name; protected CarTemplate(String name){ this.name = name; } protected abstract void buildWheel(); protected abstract void buildEngine(); protected abstract void buildCarbody(); protected abstract void buildCarlight(); public final void buildCar(){ buildWheel(); buildEngine(); buildCarbody(); buildCarlight(); } }
然后創(chuàng)建一個(gè)造路虎車的子類,用這個(gè)子類去繼承造車的公有模塊類CarTemplate。然后在方法中完善造路虎車特有的功能,代碼如下:
public class LandRover extends CarTemplate{ public LandRover(String name) { super(name); } @Override protected void buildWheel() { System.out.println(name + "越野車輪"); } @Override protected void buildEngine() { System.out.println(name + "柴油發(fā)動(dòng)機(jī)"); } @Override protected void buildCarbody() { System.out.println(name + "SUV越野車型"); } @Override protected void buildCarlight() { System.out.println(name + "普通車燈"); } }
再創(chuàng)建一個(gè)造奧迪的子類,同樣用這個(gè)子類繼承模板類,并完善造奧迪的方法,代碼如下:
public class Audi extends CarTemplate { public Audi(String name) { super(name); } @Override protected void buildWheel() { System.out.println(name + "的普通轎車車輪"); } @Override protected void buildEngine() { System.out.println(name + "的汽油發(fā)動(dòng)機(jī)"); } @Override protected void buildCarbody() { System.out.println(name + "的豪華舒適性車身"); } @Override protected void buildCarlight() { System.out.println(name + "的獨(dú)特魔力車燈"); } }
2. 測(cè)試
public class TemplateTest { public static void main(String[] args) { CarTemplate car1 = new LandRover("路虎"); CarTemplate car2 = new Audi("奧迪"); car1.buildCar(); car2.buildCar(); } }
3. 執(zhí)行結(jié)果
所有步驟都已完成,奧迪和路虎車運(yùn)用統(tǒng)一模板,但是通過(guò)在子類中完善各自不同的方法而達(dá)到目的
1. 觀察者模式
觀察者模式也被稱為發(fā)布-訂閱(Publish/Subscribe)模式,它屬于行為型模式的一種。觀察者模式定義了一種一對(duì)多的依賴關(guān)系,一個(gè)主題對(duì)象可被多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽(tīng)。當(dāng)這個(gè)主題對(duì)象狀態(tài)變化時(shí),會(huì)通知所有觀察者對(duì)象并作出相應(yīng)處理邏輯。
2. 觀察者模式包含四個(gè)角色
前面說(shuō)到觀察者模式也被稱為發(fā)布-訂閱模式,這里我就用一個(gè)微信公眾號(hào)發(fā)布文章和用戶訂閱公眾號(hào)接收文章的例子。用戶訂閱了公眾號(hào)就可以接收公眾號(hào)發(fā)布的信息文章,當(dāng)用戶對(duì)此類型公眾號(hào)不感興趣的時(shí)候就可以取消訂閱,這時(shí)候就接收不到公眾號(hào)發(fā)布的文章。用戶就是一個(gè)觀察者,公眾號(hào)就是被觀察者,被觀察者與觀察者之間的關(guān)系是一對(duì)多。接下來(lái)我將用具體代碼來(lái)實(shí)現(xiàn)這個(gè)demo。
3. 具體實(shí)現(xiàn)
①.首先創(chuàng)建一個(gè)被觀察者抽象接口,創(chuàng)建注冊(cè)觀察者,取消觀察者和提醒所有觀察者更新消息的方法,用途是用戶訂閱、取消訂閱和接收消息。
public interface Observable { //注冊(cè)觀察者 void registerObserver(Observer observer); //取消觀察者 void removeObserver(Observer observer); //通知所有觀察者更新消息 void notifyObserver(); }
②.定義一個(gè)抽象觀察者接口
public interface Observer { void update(String message); }
③.定義被觀察者,實(shí)現(xiàn)了Observable接口,對(duì)Observable接口的三個(gè)方法進(jìn)行了具體實(shí)現(xiàn),同時(shí)有一個(gè)List集合,用以保存注冊(cè)的觀察者,等需要通知觀察者時(shí),遍歷該集合即可。
public class WeChatServer implements Observable{ private Listlist; private String message; public WeChatServer(){ list = new ArrayList (); } @Override public void registerObserver(Observer o) { list.add(o); } @Override public void removeObserver(Observer o) { if(!list.isEmpty()){ list.remove(o); } } @Override public void notifyObserver() { for (int i = 0; i < list.size(); i++){ Observer observer = list.get(i); observer.update(message); } } public void setInfomation(String s){ this.message = s; System.out.println("公眾號(hào)推送消息是"+s); notifyObserver(); } }
④.創(chuàng)建具體的觀察者,這里具體的觀察者也就是用戶。
public class User implements Observer { private String name; private String message; public User(String name) { this.name = name; } @Override public void update(String message) { this.message = message; read(); } public void read(){ System.out.println(name + "接收到推送消息" + message); } }
⑤.接下來(lái)就是具體的測(cè)試類,假設(shè)現(xiàn)在有三個(gè)用戶訂閱了公眾號(hào),公眾號(hào)發(fā)布了一條信息是PHP是世界上最好的語(yǔ)言,此時(shí)java開(kāi)發(fā)工程師李四接收到信息后頗為不滿,于是果斷取消訂閱。后來(lái)公眾號(hào)又發(fā)布了一條信息是:java是世界上最好的語(yǔ)言,此時(shí)取消訂閱的李四已經(jīng)接收不到這條信息了。
public class ObserverTest { public static void main(String[] args) { WeChatServer server = new WeChatServer(); Observer userZhang = new User("ZhangSan"); Observer userLi = new User("LiSi"); Observer userWang = new User("WangWu"); server.registerObserver(userZhang); server.registerObserver(userLi); server.registerObserver(userWang); server.setInfomation("PHP是世界上最好用的語(yǔ)言!"); System.out.println("----------------------------------------------"); //李四取消訂閱 server.removeObserver(userLi); server.setInfomation("JAVA是世界上最好用的語(yǔ)言!"); } }
送個(gè)小福利,筆者最近整理了一些Java后端面試題,需要的朋友私信我 【888】 即可免費(fèi)領(lǐng)?。?/strong>
本文為作者獨(dú)立觀點(diǎn),不代表鳥(niǎo)哥筆記立場(chǎng),未經(jīng)允許不得轉(zhuǎn)載。
《鳥(niǎo)哥筆記版權(quán)及免責(zé)申明》 如對(duì)文章、圖片、字體等版權(quán)有疑問(wèn),請(qǐng)點(diǎn)擊 反饋舉報(bào)
我們致力于提供一個(gè)高質(zhì)量?jī)?nèi)容的交流平臺(tái)。為落實(shí)國(guó)家互聯(lián)網(wǎng)信息辦公室“依法管網(wǎng)、依法辦網(wǎng)、依法上網(wǎng)”的要求,為完善跟帖評(píng)論自律管理,為了保護(hù)用戶創(chuàng)造的內(nèi)容、維護(hù)開(kāi)放、真實(shí)、專業(yè)的平臺(tái)氛圍,我們團(tuán)隊(duì)將依據(jù)本公約中的條款對(duì)注冊(cè)用戶和發(fā)布在本平臺(tái)的內(nèi)容進(jìn)行管理。平臺(tái)鼓勵(lì)用戶創(chuàng)作、發(fā)布優(yōu)質(zhì)內(nèi)容,同時(shí)也將采取必要措施管理違法、侵權(quán)或有其他不良影響的網(wǎng)絡(luò)信息。
一、根據(jù)《網(wǎng)絡(luò)信息內(nèi)容生態(tài)治理規(guī)定》《中華人民共和國(guó)未成年人保護(hù)法》等法律法規(guī),對(duì)以下違法、不良信息或存在危害的行為進(jìn)行處理。
1. 違反法律法規(guī)的信息,主要表現(xiàn)為:
1)反對(duì)憲法所確定的基本原則;
2)危害國(guó)家安全,泄露國(guó)家秘密,顛覆國(guó)家政權(quán),破壞國(guó)家統(tǒng)一,損害國(guó)家榮譽(yù)和利益;
3)侮辱、濫用英烈形象,歪曲、丑化、褻瀆、否定英雄烈士事跡和精神,以侮辱、誹謗或者其他方式侵害英雄烈士的姓名、肖像、名譽(yù)、榮譽(yù);
4)宣揚(yáng)恐怖主義、極端主義或者煽動(dòng)實(shí)施恐怖活動(dòng)、極端主義活動(dòng);
5)煽動(dòng)民族仇恨、民族歧視,破壞民族團(tuán)結(jié);
6)破壞國(guó)家宗教政策,宣揚(yáng)邪教和封建迷信;
7)散布謠言,擾亂社會(huì)秩序,破壞社會(huì)穩(wěn)定;
8)宣揚(yáng)淫穢、色情、賭博、暴力、兇殺、恐怖或者教唆犯罪;
9)煽動(dòng)非法集會(huì)、結(jié)社、游行、示威、聚眾擾亂社會(huì)秩序;
10)侮辱或者誹謗他人,侵害他人名譽(yù)、隱私和其他合法權(quán)益;
11)通過(guò)網(wǎng)絡(luò)以文字、圖片、音視頻等形式,對(duì)未成年人實(shí)施侮辱、誹謗、威脅或者惡意損害未成年人形象進(jìn)行網(wǎng)絡(luò)欺凌的;
12)危害未成年人身心健康的;
13)含有法律、行政法規(guī)禁止的其他內(nèi)容;
2. 不友善:不尊重用戶及其所貢獻(xiàn)內(nèi)容的信息或行為。主要表現(xiàn)為:
1)輕蔑:貶低、輕視他人及其勞動(dòng)成果;
2)誹謗:捏造、散布虛假事實(shí),損害他人名譽(yù);
3)嘲諷:以比喻、夸張、侮辱性的手法對(duì)他人或其行為進(jìn)行揭露或描述,以此來(lái)激怒他人;
4)挑釁:以不友好的方式激怒他人,意圖使對(duì)方對(duì)自己的言論作出回應(yīng),蓄意制造事端;
5)羞辱:貶低他人的能力、行為、生理或身份特征,讓對(duì)方難堪;
6)謾罵:以不文明的語(yǔ)言對(duì)他人進(jìn)行負(fù)面評(píng)價(jià);
7)歧視:煽動(dòng)人群歧視、地域歧視等,針對(duì)他人的民族、種族、宗教、性取向、性別、年齡、地域、生理特征等身份或者歸類的攻擊;
8)威脅:許諾以不良的后果來(lái)迫使他人服從自己的意志;
3. 發(fā)布垃圾廣告信息:以推廣曝光為目的,發(fā)布影響用戶體驗(yàn)、擾亂本網(wǎng)站秩序的內(nèi)容,或進(jìn)行相關(guān)行為。主要表現(xiàn)為:
1)多次發(fā)布包含售賣產(chǎn)品、提供服務(wù)、宣傳推廣內(nèi)容的垃圾廣告。包括但不限于以下幾種形式:
2)單個(gè)帳號(hào)多次發(fā)布包含垃圾廣告的內(nèi)容;
3)多個(gè)廣告帳號(hào)互相配合發(fā)布、傳播包含垃圾廣告的內(nèi)容;
4)多次發(fā)布包含欺騙性外鏈的內(nèi)容,如未注明的淘寶客鏈接、跳轉(zhuǎn)網(wǎng)站等,誘騙用戶點(diǎn)擊鏈接
5)發(fā)布大量包含推廣鏈接、產(chǎn)品、品牌等內(nèi)容獲取搜索引擎中的不正當(dāng)曝光;
6)購(gòu)買或出售帳號(hào)之間虛假地互動(dòng),發(fā)布干擾網(wǎng)站秩序的推廣內(nèi)容及相關(guān)交易。
7)發(fā)布包含欺騙性的惡意營(yíng)銷內(nèi)容,如通過(guò)偽造經(jīng)歷、冒充他人等方式進(jìn)行惡意營(yíng)銷;
8)使用特殊符號(hào)、圖片等方式規(guī)避垃圾廣告內(nèi)容審核的廣告內(nèi)容。
4. 色情低俗信息,主要表現(xiàn)為:
1)包含自己或他人性經(jīng)驗(yàn)的細(xì)節(jié)描述或露骨的感受描述;
2)涉及色情段子、兩性笑話的低俗內(nèi)容;
3)配圖、頭圖中包含庸俗或挑逗性圖片的內(nèi)容;
4)帶有性暗示、性挑逗等易使人產(chǎn)生性聯(lián)想;
5)展現(xiàn)血腥、驚悚、殘忍等致人身心不適;
6)炒作緋聞、丑聞、劣跡等;
7)宣揚(yáng)低俗、庸俗、媚俗內(nèi)容。
5. 不實(shí)信息,主要表現(xiàn)為:
1)可能存在事實(shí)性錯(cuò)誤或者造謠等內(nèi)容;
2)存在事實(shí)夸大、偽造虛假經(jīng)歷等誤導(dǎo)他人的內(nèi)容;
3)偽造身份、冒充他人,通過(guò)頭像、用戶名等個(gè)人信息暗示自己具有特定身份,或與特定機(jī)構(gòu)或個(gè)人存在關(guān)聯(lián)。
6. 傳播封建迷信,主要表現(xiàn)為:
1)找人算命、測(cè)字、占卜、解夢(mèng)、化解厄運(yùn)、使用迷信方式治病;
2)求推薦算命看相大師;
3)針對(duì)具體風(fēng)水等問(wèn)題進(jìn)行求助或咨詢;
4)問(wèn)自己或他人的八字、六爻、星盤(pán)、手相、面相、五行缺失,包括通過(guò)占卜方法問(wèn)婚姻、前程、運(yùn)勢(shì),東西寵物丟了能不能找回、取名改名等;
7. 文章標(biāo)題黨,主要表現(xiàn)為:
1)以各種夸張、獵奇、不合常理的表現(xiàn)手法等行為來(lái)誘導(dǎo)用戶;
2)內(nèi)容與標(biāo)題之間存在嚴(yán)重不實(shí)或者原意扭曲;
3)使用夸張標(biāo)題,內(nèi)容與標(biāo)題嚴(yán)重不符的。
8.「飯圈」亂象行為,主要表現(xiàn)為:
1)誘導(dǎo)未成年人應(yīng)援集資、高額消費(fèi)、投票打榜
2)粉絲互撕謾罵、拉踩引戰(zhàn)、造謠攻擊、人肉搜索、侵犯隱私
3)鼓動(dòng)「飯圈」粉絲攀比炫富、奢靡享樂(lè)等行為
4)以號(hào)召粉絲、雇用網(wǎng)絡(luò)水軍、「養(yǎng)號(hào)」形式刷量控評(píng)等行為
5)通過(guò)「蹭熱點(diǎn)」、制造話題等形式干擾輿論,影響傳播秩序
9. 其他危害行為或內(nèi)容,主要表現(xiàn)為:
1)可能引發(fā)未成年人模仿不安全行為和違反社會(huì)公德行為、誘導(dǎo)未成年人不良嗜好影響未成年人身心健康的;
2)不當(dāng)評(píng)述自然災(zāi)害、重大事故等災(zāi)難的;
3)美化、粉飾侵略戰(zhàn)爭(zhēng)行為的;
4)法律、行政法規(guī)禁止,或可能對(duì)網(wǎng)絡(luò)生態(tài)造成不良影響的其他內(nèi)容。
二、違規(guī)處罰
本網(wǎng)站通過(guò)主動(dòng)發(fā)現(xiàn)和接受用戶舉報(bào)兩種方式收集違規(guī)行為信息。所有有意的降低內(nèi)容質(zhì)量、傷害平臺(tái)氛圍及欺凌未成年人或危害未成年人身心健康的行為都是不能容忍的。
當(dāng)一個(gè)用戶發(fā)布違規(guī)內(nèi)容時(shí),本網(wǎng)站將依據(jù)相關(guān)用戶違規(guī)情節(jié)嚴(yán)重程度,對(duì)帳號(hào)進(jìn)行禁言 1 天、7 天、15 天直至永久禁言或封停賬號(hào)的處罰。當(dāng)涉及欺凌未成年人、危害未成年人身心健康、通過(guò)作弊手段注冊(cè)、使用帳號(hào),或者濫用多個(gè)帳號(hào)發(fā)布違規(guī)內(nèi)容時(shí),本網(wǎng)站將加重處罰。
三、申訴
隨著平臺(tái)管理經(jīng)驗(yàn)的不斷豐富,本網(wǎng)站出于維護(hù)本網(wǎng)站氛圍和秩序的目的,將不斷完善本公約。
如果本網(wǎng)站用戶對(duì)本網(wǎng)站基于本公約規(guī)定做出的處理有異議,可以通過(guò)「建議反饋」功能向本網(wǎng)站進(jìn)行反饋。
(規(guī)則的最終解釋權(quán)歸屬本網(wǎng)站所有)