項目中使用的設計模式

項目中使用的設計模式

  • 請列舉幾個項目中常用的設計模式
  • 什么是設計模式,在項目中使用了那些設計模式
    • 動態代理模式
      • JDK動態代理
      • CGLIB動態代理
    • 單例模式
      • 懶漢式(非線程安全)
      • 餓漢式
      • 懶漢式(線程安全)
    • 工廠模式
    • 觀察者模式
    • 裝飾器模式

請列舉幾個項目中常用的設計模式

????單例模式(Singleton pattern)用于Runtime,Calendar和其他的一些類中。工廠模式(Factory pattern)被用于各種不可變的類如 Boolean,像Boolean.valueOf,觀察者模式(Observer pattern)被用于 Swing 和很多的事件監聽中。裝飾器設計模式(Decorator design pattern)被用于多個 Java IO 類中。

什么是設計模式,在項目中使用了那些設計模式

????設計模式是軟件開發人員在軟件開發過程中面臨的一般問題的解決方案。這些解決方案是眾多軟件開發人員經過相當長的一段時間的試驗和錯誤總結出來的。設計模式是代碼可用性的延伸

????設計模式分類:創建型模式結構型模式行為型模式

動態代理模式

????代理模式分為靜態代理與動態代理,靜態代理不做過多解釋(項目中不常用),動態代理分為JDK動態代理CGLIB動態代理,Spring2.x之前使用的代理模式為JDK動態代理,但仍需要定義接口才能實現功能,有一定的局限性,因此在Spring2.x之后,采用了CGLIB動態代理技術。

JDK動態代理

/*** 接口*/
public interface Target {public String  execute();
}
/*** 實現類*/
public class TargetImpl implements Target {@Overridepublic String execute() {System.out.println("Target execute");return "execute";}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;/*** 代理類*/
public class DynamicProxyHandler implements InvocationHandler {private Target target;public DynamicProxyHandler(Target target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("======before======");Object result = method.invoke(target, args);System.out.println("======after======");return result;}
}
import java.lang.reflect.Proxy;/*** 測試類*/
public class DynamicProxyTest {public static void main(String[] args) {Target target = new TargetImpl();DynamicProxyHandler handler = new DynamicProxyHandler(target);Target proxy = (Target) Proxy.newProxyInstance(TargetImpl.class.getClassLoader(), TargetImpl.class.getInterfaces(), handler);String result = proxy.execute();System.out.println(result);}
}

輸出結果為

======before======
Target execute
======after======
execute

CGLIB動態代理

????CGLib采用了非常底層的字節碼技術,也就是ASM 字節碼操作框架,在運行時動態生成被代理類的子類字節碼。該子類重寫了父類(被代理類)的所有飛final方法。因此CGLIB的局限性也在于此,被代理類不能繼承其他類或被final修飾的類。JDK動態代理與CGLib動態代理均是實現Spring AOP的基礎。

/*** 目標類*/
public class Target {public String execute() {String message = "======test======";System.out.println(message);return message;}
}
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** 通用代理類*/
public class MyMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("======MethodInterceptor start======");// 使用invokeSuper而不是invoke,避免無限遞歸Object result = methodProxy.invokeSuper(o, objects);System.out.println("======MethodInterceptor end======");return result;}
}
import net.sf.cglib.proxy.Enhancer;/*** 測試類*/
public class CgLibTest {public static void main(String[] args) {System.out.println("***************");CgLibTest test = new CgLibTest();Target proxyTarget = (Target) test.createProxy(Target.class);String res = proxyTarget.execute();System.out.println(res);}public Object createProxy(Class targetClass) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(targetClass);enhancer.setCallback(new MyMethodInterceptor());return enhancer.create();}
}

輸出結果為

***************
======MethodInterceptor start======
======test======
======MethodInterceptor end======
======test======

代理類的對象生成過程由Enhancer類實現,大概步驟如下:

  1. 生成代理類Class的二進制字節碼;
  2. 通過Class。forName加載二進制字節碼,生成Class對象;
  3. 通過反射機制獲取實例構造,并初始代理類對象。

單例模式

????單例模式是Java中最簡單的設計模式之一。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。意圖:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。主要解決:一個全局使用的類頻繁的創建與銷毀。單利模式主要分為懶漢餓漢,他倆的區別在于創建對象的時機,一個是當你調用類的getInstance()方法時,才會初始化對象,而另一個在類初始化時,就會創建對象,他倆只會創建同一個對象。

懶漢式(非線程安全)

public class Singleton {private static Singleton instance;// 私有化構造方法private Singleton() {}// 提供一個對象,全局僅創建一次public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

餓漢式

public class Singleton {private static Singleton instance = new Singleton();// 私有化構造方法private Singleton() {}public static Singleton getInstance() {return instance;}
}

懶漢式(線程安全)

public class Singleton {// 確保可見性與有序性private static volatile Singleton instance = null;// 構造方法私有化private Singleton() {}// 雙重校驗鎖 + volatilepublic static Singleton getInstance(){if (instance == null) {synchronized (Singleton.class) {// 避免CPU切換到另一個線程創建對象,創建完再切換回來if (instance == null) {instance = new Singleton();}}}return instance;}
}

工廠模式

????工廠模式是Java中最場景的設計模式之一。這種類型的設計模式屬于創建者模式,它提供了一種創建對象的最佳方式。意圖:定義一個創建對象的接口,讓其子類自己決定實例化哪一個工廠類,工廠模式使其創建過程延遲到子類進行。主要解決:主要解決接口選擇的問題。
建一個 Shape 接口和實現 Shape 接口的實體類,然后定義工廠類 ShapeFactory。用 ShapeFactory 來獲取 Shape 對象。它將向 ShapeFactory 傳遞信息,以便獲取它所需對象的類型。
步驟1:創建一個接口
Shapa.java

public interface Shape {void draw();
}

步驟2:創建實現接口的實體類Rectangle.java、

public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Inside Rectangle::draw() method");}
}

Square.java

public class Square implements Shape{@Overridepublic void draw() {System.out.println("Inside Square::draw() method.");}
}

Circle.java

public class Circle implements Shape {@Overridepublic void draw() {System.out.println("Inside Circle::draw() method.");}
}

步驟3:創建一個工廠,生成基于給定信息的實體類對象。
ShapeFactory.java

public class ShapeFactory {// 使用getShape() 方法獲取形狀類型的對象public Shape getShape(String shapeType) {if (shapeType == null) {return null;}shapeType = shapeType.toLowerCase(Locale.ROOT);switch (shapeType){case "circle":return new Circle();case "rectangle":return new Rectangle();case "square":return new Square();default: return null;}}
}

步驟4:使用該工廠,通過傳遞類型信息來獲取實體類的對象。
FactoryPatternDemo.java

public class FactoryPatternDemo {public static void main(String[] args) {ShapeFactory shapeFactory = new ShapeFactory();// 獲取Circle對象,并調用它的draw方法Shape shape1 = shapeFactory.getShape("CIRCLE");shape1.draw();// 獲取Rectangle對象,并調用它的draw方法Shape shape2 = shapeFactory.getShape("RECTANGLE");shape2.draw();// 獲取Square對象,并調用它的draw方法Shape shape3 = shapeFactory.getShape("SQUARE");shape3.draw();}
}

步驟5:驗證輸出結果

Inside Circle::draw() method.
Inside Rectangle::draw() method
Inside Square::draw() method.

觀察者模式

????觀察者模式屬于行為模式。當對象間存在一對多的關系時,則使用觀察者模式。比如,當一個對象被修改時,則會自動通知它的依賴對象。意圖:定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的對象都會得到通知并被自動更新。主要解決:一個對象狀態改變給其他對象通知的問題,而且要考慮到易用性和低耦合,保證高度的協作。

????實現:觀察者模式使用三個類Subject、Observer和Client。Subject對象帶有綁定觀察者到Client對象和從Client對象解綁觀察者的方法。
在這里插入圖片描述
步驟1:創建Subject類
Subject.java

public class Subject {private List<Observer> observers = new ArrayList<>();private int state;public int getState() {return state;}public void setState(int state){this.state = state;notifyAllObservers();}public void attach(Observer observer) {observers.add(observer);}public void notifyAllObservers() {for(Observer observer : observers) {observer.update();}}
}

步驟2:創建Observer類
Observer.java

public abstract class Observer {protected Subject subject;public abstract void update();
}

步驟3:創建實體觀察者類:
BinaryObserver.java

public class BinaryObserver extends Observer{public BinaryObserver(Subject subject){this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {System.out.println("Binary String" + Integer.toBinaryString(subject.getState()));}
}

OctalObserver.java

public class OctalObserver extends Observer{public OctalObserver(Subject subject){this.subject = subject; this.subject.attach(this);}@Overridepublic void update() {System.out.println("Octal String: " + Integer.toOctalString(subject.getState()));}
}

HexaObserver.java

public class HexaObserver extends Observer{public HexaObserver(Subject subject){this.subject = subject; this.subject.attach(this);}@Overridepublic void update() {System.out.println("Hex String: " + Integer.toHexString(subject.getState()).toUpperCase());}
}

步驟4:使用SUbject和實體類觀察者對象
ObserverPatternDemo.java

public class ObserverPatternDemo {public static void main(String[] args) {Subject subject = new Subject();new BinaryObserver(subject);new OctalObserver(subject);new HexaObserver(subject);System.out.println("First state change: 15");subject.setState(15);System.out.println("------------");System.out.println("Second state change: 10");subject.setState(10);}
}

步驟5:驗證結果

First state change: 15
Binary String: 1111
Octal String: 17
Hex String: F
------------
Second state change: 10
Binary String: 1010
Octal String: 12
Hex String: A

裝飾器模式

????裝飾器模式允許向一個現有的對象添加新功能,同時又不改變其結構。這種類型的設計模式屬于結構型模式,它是作為現有的一個類包裝。意圖:動態代給一個對象添加一些額外的職責。就增加功能來說,裝飾器模式相比生成子類更為靈活。主要解決:一般的,我們為了拓展一個類經常使用繼承方式實現,由于繼承為類引入靜態特征,并且隨著擴展功能的增多,子類會很膨脹。

????實現:我們將創建一個Shape接口和實現Shape接口的實體類。然后我們創建一個實現了Shape接口的抽象裝飾類ShapeDecorator,并且把Shape對象作為它的實例變量。
RedShapeDecorator是實現了ShapeDecorator的實體類;
DecoratorPatternDemo是我們的演示類使用RedShapeDecorator來裝飾Shape對象。
在這里插入圖片描述
步驟1:創建一個接口:
Shape.java

public interface Shape {void draw();
}

步驟2:創建實現接口的實體類
Rectangle.java

public class Rectangle implements Shape{@Overridepublic void draw() {System.out.println("Shape: Rectangle");}
}

Circle.java

public class Circle implements Shape{@Overridepublic void draw() {System.out.println("Shape Circle");}
}

步驟3:創建實現了Shape接口的抽象裝飾類
ShapeDecorator.java

public abstract class ShapeDecorator implements Shape{protected Shape decoratorShape;public ShapeDecorator(Shape decoratorShape){this.decoratorShape = decoratorShape;}@Overridepublic void draw(){decoratorShape.draw();}
}

步驟4:創建擴展了ShapeDecorator類的實體裝飾類
RedShapeDecorator.java

public class RedShapeDecorator extends ShapeDecorator{public RedShapeDecorator(Shape decoratorShape) {super(decoratorShape);}@Overridepublic void draw(){decoratorShape.draw();setRedBorder(decoratorShape);}private void setRedBorder(Shape decoratorShape){System.out.println("Border Color: Red");}
}

步驟5:使用RedShape來裝飾Shape對象
DecoratorPatternDemo.java

public class DecoratorPatternDemo {public static void main(String[] args) {Shape circle = new Circle();Shape redCircle = new RedShapeDecorator(new Circle());Shape redRectangle = new RedShapeDecorator(new Rectangle());System.out.println("Circle with normal border");circle.draw();System.out.println("\nCircle of red border");redCircle.draw();System.out.println("\nRectangle of red border");redRectangle.draw();}
}

步驟6:驗證結果

Circle with normal border
Shape CircleCircle of red border
Shape Circle
Border Color: RedRectangle of red border
Shape: Rectangle
Border Color: Red

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/917965.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/917965.shtml
英文地址,請注明出處:http://en.pswp.cn/news/917965.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

實戰教程:從“對象文件為空“到倉庫重生——修復 Git 倉庫損壞全記錄

文章目錄實戰教程&#xff1a;從"對象文件為空"到倉庫重生——修復 Git 倉庫損壞全記錄案發現場&#xff1a;一個嚴重損壞的倉庫修復之旅&#xff1a;四步讓倉庫重獲新生準備工作&#xff1a;創建安全備份第 1 步&#xff1a;清理戰場——刪除所有空對象第 2 步&…

ansible 操作家族(ansible_os_family)信息

1. 操作系統系列 &#xff08;ansible_os_family&#xff09;ansible web -m setup -a filteransible_os_family2. 操作系統家族為 RedHat 時執行任務--- - hosts: websrvsremote_user: roottasks:- name: Install package on RedHat systemsyum:name: httpdstate: presentwhen…

一文學會c++繼承 組合

文章目錄繼承簡介定義訪問限定符和繼承方式?基類派生類賦值轉換繼承的作用域派生類的默認成員函數繼承與友元繼承與靜態成員?復雜的菱形繼承虛擬繼承組合繼承簡介 繼承是面向對象程序設計代碼復用的重要手段&#xff0c;使得程序員可以在保持原類的基礎上擴展&#xff0c;新…

.Net下載共享文件夾中的文件

由于IIS站點權限等問題&#xff0c;總是沒找到處理辦法&#xff0c;所以改用外掛的winform的方式來下載共享文件&#xff08;也可以改為使用windows服務的方式&#xff09;。 前提需要先在資源管理器中登錄到共享文件夾&#xff0c;確保系統能訪問。 服務端代碼 (.NET后端) usi…

目標檢測數據集 - 眼睛瞳孔檢測數據集下載「包含COCO、YOLO兩種格式」

數據集介紹&#xff1a;眼睛瞳孔檢測數據集&#xff0c;真實采集高質量人臉眼部圖片數據&#xff0c;適用于人臉定位、人臉疾病如白內障等疾病的視覺檢測。數據標注標簽包括 eyepupil 瞳孔一 個缺陷類別&#xff1b;適用實際項目應用&#xff1a;眼睛瞳孔檢測項目&#xff0c;以…

Keil MDK-ARM V5.42a 完整安裝教程

文章目錄一、安裝前期準備二、Keil MDK-ARM 主程序安裝三、器件支持包&#xff08;Pack&#xff09;安裝四、許可證激活五、安裝驗證Keil MDK&#xff08;Microcontroller Development Kit&#xff09;是針對 Arm Cortex-M 系列微控制器的專業開發環境&#xff0c;集成了 μVis…

WPF中引用其他元素各種方法

在WPF中&#xff0c;引用其他元素的方式有多種&#xff0c;每種方式適用于不同場景&#xff0c;各有優缺點。除了x:Reference&#xff0c;常用的還有以下幾種&#xff1a; 一、ElementName 綁定&#xff08;最常用的XAML綁定方式&#xff09; 通過元素的x:Name屬性引用同一作用…

Python生成統計學公式

一元線性回歸模型 2.1回歸分析概述/25 一、回歸分析基本概念/25 二、總體回歸函數/27 三、隨機誤差項/29 四、樣本回歸函數/30 2.2 一元線性回歸模型的參數估計/32 一、參數估計的普通最小二乘法/32 二、擬合優度/35 2.3基本假設與普通最小二乘估計量的統計性質/36 一、一元線性…

網絡工程師--華為命令專題

一、交換機 交換機分類&#xff1a;1.根據交換方式劃分&#xff1a;&#xff08;1&#xff09;存儲轉發式交換&#xff08;Store and Forward&#xff09;&#xff08;2&#xff09;直通式交換&#xff08;Cut-through&#xff09;&#xff08;3&#xff09;碎片過濾式交換&…

判斷可編輯div的光標是否在最前面

要判斷一個可編輯div(contenteditable)中的光標是否位于最前面&#xff0c;可以使用以下幾種方法&#xff1a; 方法一&#xff1a;使用Selection和Range API function isCaretAtStart(div) {const selection window.getSelection();if (selection.rangeCount 0) return false…

【unity實戰】使用Unity程序化生成3D隨機地牢(附項目源碼)

最終效果 文章目錄最終效果前言1、理解程序生成的核心概念2、種子值的核心作用3、程序生成的實際應用4、主流程序生成技術概覽5、選擇合適的技術實戰1、素材2、生成一面墻變換矩陣數據3、渲染墻壁4、加點隨機不同的墻壁效果5、繪制四面墻壁4、在四個角落生成支柱5、生成地板6、…

多賬號管理方案:解析一款免Root的App分身工具

之前有小伙伴問阿燦有沒有可以軟件分身的免費軟件&#xff0c;后來阿燦找到了一款可以無限分身的app感覺很實用&#xff0c;只有10M大小 02軟件介紹說白了它能給各種app和游戲做分身&#xff0c;包括V信、qQ、某音、某付寶這些&#xff0c;而且支持最新的安卓15系統。每個分身…

(附源碼)基于PHP和Vue的網上購物平臺

內容摘要 內容摘要: 隨著互聯網技術的迅猛發展&#xff0c;網上購物已成為人們日常生活的重要組成部分。本文圍繞PHPVue技術棧構建的網上購物平臺展開研究&#xff0c;深入探討了該平臺的架構設計與實現細節。平臺前端采用Vue框架&#xff0c;利用其組件化開發和數據驅動的特性…

51單片機

中斷系統1.什么是中斷當CPU正在處理某件事的時候外界發生了緊急事件請求&#xff0c;要求CPU暫停當前的工作&#xff0c;轉而去處理這個緊急事件&#xff0c;處理完以后&#xff0c;再回到原來被中斷的地方&#xff0c;繼續原來的工作&#xff0c;這樣的過程稱為中斷2.為什么要…

前端開發:HTML(5)—— 表單

下面我們來學習表單。 目錄 什么是Web表單&#xff1f; 表單標簽 1.form標簽 2.輸入框 文本框和密碼框 單選框和復選框 1.單選框 2.復選框 3.按鈕 &#xff08;1&#xff09;普通按鈕 &#xff08;2&#xff09;提交按鈕 &#xff08;3&#xff09;重置按鈕 &#…

【YOLOv8改進 - C2f融合】C2f融合SFS-Conv(空間 - 頻率選擇卷積)提升特征多樣性,同時減少參數和計算量

YOLOv8目標檢測創新改進與實戰案例專欄 專欄目錄: YOLOv8有效改進系列及項目實戰目錄 包含卷積,主干 注意力,檢測頭等創新機制 以及 各種目標檢測分割項目實戰案例 專欄鏈接: YOLOv8基礎解析+創新改進+實戰案例 文章目錄 YOLOv8目標檢測創新改進與實戰案例專欄 介紹 摘要 文…

如何將照片從POCO手機傳輸到Mac電腦

將照片從POCO手機傳輸到Mac電腦可能會有些困難&#xff0c;因為與iPhone不同&#xff0c;POCO設備沒有原生的macOS支持。這常常讓用戶尋找簡單、有效的方法來移動圖片&#xff0c;同時避免丟失質量&#xff0c;節省時間&#xff0c;并避免復雜的軟件設置。如果你想知道如何將照…

最新教程 | CentOS 7 內網環境 Nginx + ECharts 頁面離線部署手冊(RPM 安裝方式)

&#x1f4c1; 一、準備階段&#xff08;在聯網電腦上完成&#xff09; 1.1 下載 Nginx 官方 RPM 安裝包 在聯網電腦瀏覽器中訪問 Nginx 官方穩定版本倉庫&#xff1a; &#x1f517; 地址&#xff1a;http://nginx.org/packages/centos/7/x86_64/ ??云盤&#xff1a;htt…

Redis 常用數據類型 (下)

文章目錄前言一 Hash 哈希1. Hash 相關命令hset 和 hgethexistshdelhkeyshvalshgetallhmgethlenhsetnxhincrbyincrbyfloat2. Hash 命令小結3. Hash 內部編碼Hash 在緩存中的應用場景介紹緩存方式對比二、List 列表1. LIST總體介紹2. List 普通命令lpushlpushxrpushrpushxlrange…

Java Lambda表達式:簡潔高效的函數式編程

1 lambda表達式Lambda 表達式本質是一個匿名函數&#xff0c;用于把函數作為參數&#xff0c;傳入方法中&#xff0c;實現函數式編程風格。使用Lambda 表達式可以使代碼變的更加簡潔緊湊。語法格式&#xff1a;(parameters)-> expression 或 (parameters)->{ statements…