日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

JAVA常用的七种设计模式

發(fā)布時(shí)間:2023/12/10 asp.net 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JAVA常用的七种设计模式 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

學(xué)習(xí)設(shè)計(jì)模式之前,我們先要了解一下設(shè)計(jì)模式的怎么來(lái)的?

對(duì)于設(shè)計(jì)人員,特別是開發(fā)人員嗎,往往受限于眼界或經(jīng)驗(yàn)不能夠體會(huì)到設(shè)計(jì)原則的實(shí)用性,或者在處理具體問(wèn)題時(shí),不知道如何把設(shè)計(jì)原則應(yīng)用到到設(shè)計(jì)和代碼,因此產(chǎn)生了“模式”。
隨著參與的項(xiàng)目越來(lái)越多,人們發(fā)現(xiàn):很多問(wèn)題并不是一個(gè)項(xiàng)目中出現(xiàn)的,它會(huì)在很多的項(xiàng)目中出現(xiàn)。于是人們就把這些問(wèn)題總結(jié)出來(lái),然后給出了解決這些問(wèn)題的方案,而這些方案–“模式”(解決問(wèn)題的套路)。

設(shè)計(jì)模式的分類

1.創(chuàng)建模式:創(chuàng)建一些特殊的對(duì)象,或者在特殊要求下創(chuàng)建對(duì)象。
2.結(jié)構(gòu)模式:主要利用組合/聚合或者繼承,讓類與類能夠形成某種關(guān)聯(lián)關(guān)系 – 代理。
3.行為模式:刻畫了類和對(duì)象交換及分配職責(zé)的方式。

接下來(lái)我們正式介紹七種常用的設(shè)計(jì)模式

單例模式

1.餓漢模式(最基本的單例模式)

類加載時(shí),會(huì)直接實(shí)例化單例對(duì)象,以后都返回該對(duì)象的引用。

  • 缺點(diǎn):類加載時(shí),會(huì)直接實(shí)例化單例對(duì)象,不管是否使用到該單例對(duì)象,浪費(fèi)內(nèi)存。
  • 優(yōu)點(diǎn):沒(méi)有枷鎖,執(zhí)行效率高,線程安全的實(shí)例。
public class Singleton{private Singleton{}//創(chuàng)建本類的私有構(gòu)造方法private static Singleton singleton = new Singleton();public static Singleton getInstance(){return singleton;}}

2.懶漢模式(線程不安全、線程安全但效率低)

不要直接在類加載時(shí)實(shí)例化,而是在調(diào)用方法時(shí),再實(shí)例化。

  • 優(yōu)點(diǎn):不會(huì)占用內(nèi)存
  • 缺點(diǎn):安全方面 單線程情況下,是安全的,但是在多線程下,多個(gè)線程可能同時(shí)執(zhí)行singleton == null 都為true,會(huì)創(chuàng)建多個(gè)實(shí)例在內(nèi)存中。
public class LazySingleton{private LazySingleton(){}private static LazySingleton singleton;public static LazySingleton getInstance(){if(singleton == null){singleton = new LazySingleton();}return singleton;}}

2.1懶漢模式(雙重檢驗(yàn)?zāi)J?線程安全,且效率高的) 把鎖的粒度變小,只鎖第一次初始化時(shí))

  • 實(shí)例會(huì)在調(diào)用getInstance方法時(shí)創(chuàng)建,僅在第一調(diào)用初始化時(shí)需要鎖住。
public class LazySingleton{private LazySingleton(){}private static LazySingleton singleton;public static LazySingleton getInstance(){/*雙重檢驗(yàn)首先先判斷實(shí)例是否為null,為null則使用synchronized鎖住類,然后在同步塊中,再一次判斷實(shí)例是否為null,為null則初始化實(shí)例。synchronized(需要鎖的對(duì)象){}*/if(singleton == null){synchronized(LazySingleton .class){if(singleton == null){singleton = new LazySingleton();}}}return singleton;}}

3.內(nèi)部類實(shí)現(xiàn)模式

通過(guò)靜態(tài)內(nèi)部類,完成單例模式的創(chuàng)建。

  • 在外部類加載時(shí),并不會(huì)加載內(nèi)部類,也就是不會(huì)執(zhí)行new 實(shí)例(),這屬于懶加載。
  • 只有第一次調(diào)用getInstance方法時(shí),才會(huì)加載。
public class InnerSingleton{private InnerSingleton(){}private static class Inner{private static InnerSingleton instance = new InnerSingleton();}public static InnerSingleton getInstance(){return Inner.instance;}}

4.枚舉實(shí)現(xiàn)

通過(guò)枚舉創(chuàng)建 單例模式。

  • 實(shí)現(xiàn)單例的最佳方法。簡(jiǎn)潔,支持自動(dòng)序列化機(jī)制,防止多次實(shí)例化,但目前還沒(méi)有被廣泛采用。
public class EnumSingleton{private EnumSingleton(){}private static enum SinEnum{//自定義的枚舉值,如果沒(méi)有該自定義枚舉值,無(wú)法獲取枚舉對(duì)象SIN;private EnumSingleton es = new EnumSingleton();}public static EnumSingleton getInstance(){SinEnum s = SinEnum.SIN;return s.es;}}

工廠模式

講使用者和對(duì)象的生產(chǎn)者進(jìn)行分離。

在工廠模式中,幾乎都有三種角色,工廠(抽象工廠、具體工廠) 產(chǎn)品(抽象產(chǎn)品、具體產(chǎn)品) 使用者。使用者想要使用產(chǎn)品,不用自己去生產(chǎn)產(chǎn)品,把生產(chǎn)的動(dòng)作交給工廠去做,使用者只需要從工廠提供產(chǎn)品的位置(方法)去拿就好。

  • 1.簡(jiǎn)單工廠模式–顧客需要給出清單。
    變化點(diǎn)在產(chǎn)品對(duì)象上,所以我們會(huì)抽象產(chǎn)品,然后通過(guò)一個(gè)工廠,根據(jù)不同的情況產(chǎn)生不同的產(chǎn)品對(duì)象。

  • 2.工廠方法模式–根據(jù)工廠能產(chǎn)生什么顧客拿什么。
    工廠可以產(chǎn)生統(tǒng)一品牌的商品,會(huì)根據(jù)商品去抽象工廠,對(duì)每一個(gè)產(chǎn)品,提供一個(gè)工廠實(shí)現(xiàn)類。

  • 3.抽象工廠模式–根據(jù)工廠能產(chǎn)生什么顧客拿什么,但是工廠能產(chǎn)生的產(chǎn)品會(huì)有多種品牌。
    超級(jí)工廠,可以生產(chǎn)不同品牌的各種產(chǎn)品,抽象出超級(jí)工廠,也要抽象出產(chǎn)品,然后根據(jù)不同的品牌給出該品牌商品的工工廠實(shí)現(xiàn)類。

原型模式

根據(jù)一個(gè)已經(jīng)存在的對(duì)象,創(chuàng)建一個(gè)和他一樣的對(duì)象。-- 克隆

淺克隆-- 利用Object中clone()實(shí)現(xiàn)

1.讓被克隆的類實(shí)現(xiàn)Cloneable接口。

2.重寫clone方法,方法訪問(wèn)修飾符public。

3.對(duì)象.clone()的方式的到一個(gè)一樣的對(duì)象。

淺克隆指,被克隆的對(duì)象會(huì)產(chǎn)生一個(gè)新的,但是對(duì)象屬性不會(huì)產(chǎn)生。

public class Man implements Cloneable {private String name;public Car car = new Car();public Man clone() throws CloneNotSupportedException{Object obj = super.clone();return (Man)obj;}}

深度克隆

1.克隆對(duì)象所涉及的自定義類,需要實(shí)現(xiàn)序列化接口。

2.在需要克隆的類中,添加一個(gè)方法,完成序列化反序列化即可。

public class Man implements Cloneable,Serializable {private String name;public Car car = new Car();public Man depthClone() throws IOException, ClassNotFoundException {//獲取對(duì)象信息,把當(dāng)前對(duì)象寫入另一塊內(nèi)存ByteArrayOutputStream bo = new ByteArrayOutputStream();ObjectOutputStream objOut = new ObjectOutputStream(bo);objOut.writeObject(this);//讀取內(nèi)存 創(chuàng)建對(duì)象ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());ObjectInputStream objIn = new ObjectInputStream(bi);Object obj = objIn.readObject();return (Man) obj;}}

代理模式

1.靜態(tài)代理

根據(jù)目標(biāo)對(duì)象需要代理的行為,抽象出一個(gè)接口(包含了需要代理的行為),目標(biāo)類和代理類都需要去實(shí)現(xiàn)該接口,然后將目標(biāo)對(duì)象注入到代理類中,此時(shí)就可以在代理類中調(diào)用目標(biāo)對(duì)象的行為,并為止附加非功能性邏輯。

2.動(dòng)態(tài)代理之JDK代理

  • 第一步,實(shí)現(xiàn)接口InvocationHandler,然后重寫invoke方法,在invoke方法中調(diào)用目標(biāo)對(duì)的方法。

  • 第二步,提供一個(gè)自定義的方法,通過(guò)Proxy.newProxyInstance()得到代理對(duì)象。

public class LivePeople implements InvocationHandler {private IEat target;//目標(biāo)對(duì)象public LivePeople(IEat target) {this.target = target;}//獲取代理對(duì)象public Object getProxy() {//Proxy()類中的newProxyInstance()方法/*第一個(gè)參數(shù):目標(biāo)對(duì)象的類加載器第二個(gè)參數(shù):目標(biāo)對(duì)象實(shí)現(xiàn)的所有接口第三個(gè)參數(shù):代理類的對(duì)象*/return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("訂餐");Object returnInfo = method.invoke(target, args);//執(zhí)行目標(biāo)對(duì)象的方法System.out.println("結(jié)賬,開發(fā)票");return returnInfo;} }

3.動(dòng)態(tài)代理之Cglib代理

  • 第一步,導(dǎo)入Cglib依賴(包)。

  • 第二步,實(shí)現(xiàn)接口MethodInterceptor,重寫intercept方法,在其中完成目標(biāo)對(duì)象的方法調(diào)用。

  • 第三步,提供自定義方法,通過(guò)工具類獲取得到代理對(duì)象。

public class CglibProxy implements MethodInterceptor {private IEat target;public CglibProxy(IEat target) {this.target = target;}//給目標(biāo)對(duì)象創(chuàng)建代理對(duì)象(自定義)public Object getProxyInstance() {//創(chuàng)建工具欄對(duì)象Enhancer en = new Enhancer();//設(shè)置目標(biāo)對(duì)象父類en.setSuperclass(target.getClass());//設(shè)置回調(diào)函數(shù)en.setCallback(this);//創(chuàng)建代理對(duì)象return en.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("訂餐");Object returnInfo = methodProxy.invokeSuper(o, objects);//調(diào)用目標(biāo)對(duì)象的方法并傳入?yún)?shù)System.out.println("付款,開發(fā)票");return returnInfo;} }

裝飾器模式

對(duì)象功能的擴(kuò)展能夠根據(jù)需要來(lái)動(dòng)態(tài)地實(shí)現(xiàn)。

以咖啡舉例:

  • 1.根據(jù)對(duì)象抽象一個(gè)公共的接口。

  • 2.根據(jù)接口給出不同的實(shí)現(xiàn)類(主料類(主料類產(chǎn)生的對(duì)象就是被裝飾的對(duì)象) 和 配料類–裝飾類)。

  • 3.在配料類中注入被裝飾的對(duì)象。

  • 4.生產(chǎn)咖啡時(shí),先生產(chǎn)主料(被修飾的對(duì)象),然后用配料不斷去修飾主料。

適配器模式

使得原本不兼容的兩個(gè)接口(功能)可以兼容 – 搭建了兩個(gè)接口間的橋梁。

class Tel{public void call(){}}class Carame{public void make(){}}class Phone extends Tel{private Carame c = new Carame();public void make(){c.make();}}

實(shí)現(xiàn)適配器的方案,繼承或者依賴(推薦使用)

優(yōu)點(diǎn):

  • 可以讓沒(méi)有任何關(guān)聯(lián)的類,一起運(yùn)行;

  • 提高了類的復(fù)用

  • 靈活性好

缺點(diǎn):

  • 過(guò)多的使用適配器,會(huì)導(dǎo)致系統(tǒng)非常混亂,不容具體把控

  • java是單繼承。

觀察者模式

  • 主題類(由它產(chǎn)生的對(duì)象 就是 被觀察的對(duì)象) 繼承 Observable的類。
    在主題類,需要針對(duì)主題(價(jià)格的變化進(jìn)行關(guān)注,設(shè)置變化點(diǎn),然后通知觀察者價(jià)格有了變化)。
public class Product extends Observable {private double price;public double getPrice() {return price;}public void setPrice(double price) {this.price = price;// 通知觀察者注意到主題的變化this.setChanged();// 設(shè)置變化點(diǎn)this.notifyObservers(price);//通知觀察者} }
  • 觀察者類(由它產(chǎn)生的對(duì)象 就是 觀察者) 實(shí)現(xiàn)Observer接口。
    重寫update(當(dāng)主題發(fā)生變化時(shí),會(huì)調(diào)用方法)。
public class ProductProxy1 implements Observer {private double price;/*** 當(dāng)主題類的值發(fā)生變化后,會(huì)調(diào)用該方法* @param o 主題對(duì)象* @param arg 主題更新的值對(duì)象*/@Overridepublic void update(Observable o, Object arg) {double factoryPrice = (double) arg;this.price = factoryPrice * 1.5;}public double getPrice() {return price;} }
  • 首先產(chǎn)生主題對(duì)象(被觀察對(duì)象),產(chǎn)生觀察者對(duì)象,然后給主題對(duì)象設(shè)置觀察者,最后通過(guò)更改主題的值,測(cè)試觀察者是否有觀測(cè)到主題值的改變。
public class Test {public static void main(String[] args) {// 產(chǎn)生主題對(duì)象 -- 被觀察者Product product = new Product();// 產(chǎn)生觀察者ProductProxy1 p1 = new ProductProxy1();// 給主題對(duì)象添加觀察者product.addObserver(p1);// 主題發(fā)生變化product.setPrice(1000);System.out.println("出廠價(jià)格:"+ product.getPrice() +"\n代理商售賣價(jià)格:" + p1.getPrice());// 主題發(fā)生變化product.setPrice(2000);System.out.println("出廠價(jià)格:"+ product.getPrice() + "\n代理商售賣價(jià)格:" + p1.getPrice());} }

總結(jié)

以上是生活随笔為你收集整理的JAVA常用的七种设计模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。