一、單例模式
????????單例模式是(Singleton Pattern)Java中最常用的設計模式之一,它保證一個類僅有一個實例,并提供一個全局訪問點。
????????實現單例模式的核心是將類的構造方法私有化,以防止外部直接通過構造函數創建實例。同時,類內部需要提供一個靜態方法或變量來獲取該類的唯一實例。單例模式分為餓漢式單例(立即加載)和懶漢式單例(延遲加載)。
餓漢式單例:線程安全
public class Singleton1 {/*** 在類的內部可以訪問私有結構,所以可以在類的內部產生實例化對象*/private static Singleton1 instance = new Singleton1();/*** private 聲明構造*/private Singleton1() {}/*** 返回對象實例*/public static Singleton1 getInstance() {return instance;}
}
懶漢式單例:?
????????當多個線程并發執行 getInstance 方法時,懶漢式會存在線程安全問題,所以用到了 synchronized 來實現線程的同步,當一個線程獲得鎖的時候其他線程就只能在外等待其執行完畢。而餓漢式則不存在線程安全的問題。
public class Singleton2 {/*線程不安全*/
// // 指向自己實例的私有靜態引用
// private static Singleton2 singleton2;
//
// // 私有的構造方法
// private Singleton2(){}
//
// // 以自己實例為返回值的靜態的公有方法,靜態工廠方法
// public static Singleton2 getSingleton2(){
// // 被動創建,在真正需要使用時才去創建
// if (singleton2 == null) {
// singleton2 = new Singleton2();
// }
// return singleton2;
// }/*** 聲明變量*/private static volatile Singleton2 singleton = null;/*** 私有構造方法*/private Singleton2() {}/*** 提供對外方法* @return*/public static Singleton2 getInstance() {// 還未實例化if (singleton == null) {synchronized (Singleton2.class) {if (singleton == null) {singleton = new Singleton2();}}}return singleton;}
}
JDK 中的應用:
- java.lang.Runtime.getRuntime()
- java.util.logging.Logger
Spring 中的應用:Spring 的 Bean 默認是單例模式。可以通過 @Scope("prototype") 將其改為多例。
二、工廠模式
根據需求,在用于不同的場景下,創建不同的對象。
public interface Sender {void Send();
}public class MailSender implements Sender{@Overridepublic void Send() {System.out.println("This is mail sender...");}
}public class SmsSender implements Sender{@Overridepublic void Send() {System.out.println("This is sms sender...");}
}public class FactoryPattern {public static void main(String[] args) {Sender sender = produce("mail");sender.Send();}public static Sender produce(String str) {if ("mail".equals(str)) {return new MailSender();} else if ("sms".equals(str)) {return new SmsSender();} else {System.out.println("輸入錯誤...");return null;}}
}
????????在此基礎上,若存在多個分支判斷條件,很容易出現傳遞的字符串出錯,則不能正確創建對象,因此可以多封裝一個類,用來將分支判斷替換為每個方法,降低耦合,這種模式是多個工廠方法模式,是提供多個工廠方法,分別創建對象。?
public interface Sender {void Send();
}public class MailSender implements Sender{@Overridepublic void Send() {System.out.println("This is mail sender...");}
}public class SmsSender implements Sender{@Overridepublic void Send() {System.out.println("This is sms sender...");}
}public class SendFactory {public Sender produceMail() {return new MailSender();}public Sender produceSms() {return new SmsSender();}
}public class FactoryPattern {public static void main(String[] args) {SendFactory factory = new SendFactory();Sender sender = factory.produceMail();sender.Send();}
}
JDK 中的應用:
- java.util.Calendar.getInstance()
- javax.xml.parsers.DocumentBuilderFactory.newInstance()
Spring 中的應用:
- BeanFactory 和 ApplicationContext 都是工廠模式的體現。
?三、建造者模式
????????建造者模式用于創建復雜對象,就是將復雜對象的創建過程拆分成多個簡單對象的創建過程,并將這些簡單對象組合起來構建出復雜對象。
角色組成:
- 產品類(Product):表示被創建的復雜對象。它通常包含多個部分或者組成,并由具體的建造者逐步構建而成。?Meal
- 抽象建造者類(Builder):定義了建造復雜對象所需要的各個部分的創建方法。它通常包括多個構建方法和一個返回產品的方法。?MealBuilder
- 具體建造者類(ConcreteBuilder):實現Builder接口,并提供各個部分或者組成的構建方法。?BeefBurgerMealBuilder、ChickenMealBuilder、ShrimpMealBuilder
- 指揮者類(Director):負責控制建造者的構建順序,指揮建造者如何構建復雜對象。MealDirector
/*** @Author: EstellaQ* @Date: 2025/4/17 15:43* @Description: 產品類**/
@Data
public class Meal {//漢堡包private String burger;//薯條private String fries;//飲料private String drink;}/*** @Author: EstellaQ* @Date: 2025/4/17 15:44* @Description: 建造者接口**/
public interface MealBuilder {Meal meal=new Meal();//構建漢堡public void buildBurger();//構建薯條public void buildFries();//構建飲料public void buildDrink();public default Meal getMeal(){return meal;}
}/*** @Author: EstellaQ* @Date: 2025/4/17 15:46* @Description: 牛肉套餐建造者**/
public class BeefBurgerMealBuilder implements MealBuilder{@Overridepublic void buildBurger() {meal.setBurger("牛肉漢堡");}@Overridepublic void buildFries() {meal.setFries("大份薯條");}@Overridepublic void buildDrink() {meal.setDrink("中杯可樂");}
}/*** @Author: EstellaQ* @Date: 2025/4/17 15:46* @Description: 雞肉套餐建造者**/
public class ChickenMealBuilder implements MealBuilder{@Overridepublic void buildBurger() {meal.setBurger("雞肉漢堡");}@Overridepublic void buildFries() {meal.setFries("中份薯條");}@Overridepublic void buildDrink() {meal.setDrink("大杯果汁");}
}/*** @Author: EstellaQ* @Date: 2025/4/17 15:46* @Description: 蝦肉套餐建造者**/
public class ShrimpMealBuilder implements MealBuilder{@Overridepublic void buildBurger() {meal.setBurger("蝦肉漢堡");}@Overridepublic void buildFries() {meal.setFries("小份薯條");}@Overridepublic void buildDrink() {meal.setDrink("大杯芬達");}
}/*** @Author: EstellaQ* @Date: 2025/4/17 15:50* @Description: 指揮者**/
public class MealDirector {private MealBuilder mealBuilder;public void setMealBuilder(MealBuilder mealBuilder){this.mealBuilder=mealBuilder;}public Meal getMeal(){return mealBuilder.getMeal();}//制作套餐public void constructMeal(){mealBuilder.buildBurger();mealBuilder.buildFries();mealBuilder.buildDrink();}
}public class BuilderPattern {public static void main(String[] args) {//創建指導者MealDirector director=new MealDirector();//執導建造牛肉套餐director.setMealBuilder(new BeefBurgerMealBuilder());director.constructMeal();Meal meal = director.getMeal();System.out.println("牛肉套餐:"+meal.toString());//雞肉套餐director.setMealBuilder(new ChickenMealBuilder());director.constructMeal();Meal meal2 = director.getMeal();System.out.println("雞肉套餐:"+meal2.toString());//蝦肉套餐director.setMealBuilder(new ShrimpMealBuilder());director.constructMeal();Meal meal3 = director.getMeal();System.out.println("蝦肉套餐:"+meal3.toString());}
}
JDK 中的應用:
- StringBuilder
- Stream.Builder
Spring 中的應用:
- UriComponentsBuilder 用于構建 URI。
?四、?適配器模式
????????它允許將不兼容的對象轉換成可兼容的接口。主要目的是解決在不改變現有代碼的情況下,使不兼容的接口之間能夠正常工作,通過創建一個中間轉換的適配器來將一個對象轉換成我們所需要的接口。
角色組成
- 目標接口(target):需要適配的標準接口。
- 源對象(source):需要被適配的不兼容對象。
- 適配器對象(adapter):充當中間轉換角色,該對象將源對象轉換成目標接口。
/*** @Author: EstellaQ* @Date: 2025/4/17 16:20* @Description: 目標接口**/
public interface Target {/*** 翻譯* @param source 母語* @param target 要翻譯成的語種* @param words 內容*/void translate(String source,String target,String words);
}/*** @Author: EstellaQ* @Date: 2025/4/17 16:20* @Description: 源對象**/
public class Translator {//英——》漢public void translateInZh(String words){if("hello world!".equals(words)){System.out.println("翻譯成中文:”你好世界!“");}}//漢——》英public void translateInEn(String words){if("你好世界!".equals(words)){System.out.println("Translate in English:”hello world!“");}}
}/*** @Author: EstellaQ* @Date: 2025/4/17 16:21* @Description: 類適配器:通過多重繼承目標接口和被適配者類方式來實現適配**/
public class ClassAdapter extends Translator implements Target{@Overridepublic void translate(String source, String target, String words) {if("中文".equals(source) && "英文".equals(target)) {//漢--》英this.translateInEn(words);} else {//英--》漢this.translateInZh(words);}}
}public class AdapterPattern {public static void main(String[] args) {//創建一個類適配器對象ClassAdapter adapter=new ClassAdapter();adapter.translate("中文", "英文", "你好世界!");adapter.translate("英語","中文","hello world!");}
}
?五、?裝飾器模式
裝飾器模式在不改變原始類的基礎上,動態累積擴展其功能。原始對象和裝飾類對象都要實現原始對象的接口。
/*** @Author: EstellaQ* @Date: 2025/4/17 16:55* @Description: 原始對象的接口**/
public interface ICoffee {void makeCoffee();
}/*** @Author: EstellaQ* @Date: 2025/4/17 16:56* @Description: 原始對象**/
public class OriginalCoffee implements ICoffee{@Overridepublic void makeCoffee() {System.out.print("原味咖啡 ");}
}/*** @Author: EstellaQ* @Date: 2025/4/17 16:56* @Description: 裝飾器基類**/
public abstract class CoffeeDecorator implements ICoffee{private ICoffee coffee;public CoffeeDecorator(ICoffee coffee){this.coffee=coffee;}@Overridepublic void makeCoffee() {coffee.makeCoffee();}
}/*** @Author: EstellaQ* @Date: 2025/4/17 16:58* @Description: 加奶的裝飾**/
public class MilkDecorator extends CoffeeDecorator{public MilkDecorator(ICoffee coffee) {super(coffee);}@Overridepublic void makeCoffee() {super.makeCoffee();addMilk();}private void addMilk(){System.out.print("加奶 ");}
}/*** @Author: EstellaQ* @Date: 2025/4/17 16:58* @Description: 加糖的裝飾**/
public class SugarDecorator extends CoffeeDecorator{public SugarDecorator(ICoffee coffee) {super(coffee);}@Overridepublic void makeCoffee() {super.makeCoffee();addSugar();}private void addSugar(){System.out.print("加糖 ");}
}/*** @Author: EstellaQ* @Date: 2025/4/17 17:00* @Description: 裝飾器模式測試**/
public class DecoratorPattern {public static void main(String[] args) {//原味咖啡ICoffee coffee=new OriginalCoffee();coffee.makeCoffee();System.out.println("");//加奶的咖啡coffee=new MilkDecorator(coffee);coffee.makeCoffee();System.out.println("");//先加奶后加糖的咖啡coffee=new SugarDecorator(coffee);coffee.makeCoffee();}
}
JDK 中的應用:
- java.io.BufferedInputStream 和 java.io.BufferedOutputStream
Spring 中的應用:
- BeanPostProcessor 用于動態修改 Bean 的行為。
六、?代理模式
????????代理模式的結構比較簡單,主要是通過定義一個繼承抽象主題的代理來包含真實主題,從而實現對真實主題的訪問,下面來分析其基本結構。
角色組成:
- 抽象主題(Subject)類(業務接口類):通過接口或抽象類聲明真實主題和代理對象實現的業務方法,服務端需要實現該方法。
- 真實主題(Real Subject)類(業務實現類):實現了抽象主題中的具體業務,是代理對象所代表的真實對象,是最終要引用的對象。
- 代理(Proxy)類:提供了與真實主題相同的接口,其內部含有對真實主題的引用,它可以訪問、控制或擴展真實主題的功能。
靜態代理?
????????靜態代理服務于單個接口,我們來考慮實際工程中的一個例子,現在已經有業務代碼實現一個增刪功能,原有的業務代碼由于仍有大量程序無法改變,現在新增需求,即以后每執行一個方法輸出一個日志。
/*** @Author: EstellaQ* @Date: 2025/4/17 17:38* @Description: 業務接口**/
public interface DateService {void add();void del();
}/*** @Author: EstellaQ* @Date: 2025/4/17 17:39* @Description: 委托類**/
public class DateServiceImplA implements DateService{@Overridepublic void add() {System.out.println("成功添加!");}@Overridepublic void del() {System.out.println("成功刪除!");}
}/*** @Author: EstellaQ* @Date: 2025/4/17 17:40* @Description: 代理類**/
public class DateServiceProxy implements DateService{DateServiceImplA server = new DateServiceImplA();@Overridepublic void add() {server.add();System.out.println("程序執行add方法,記錄日志.");}@Overridepublic void del() {server.del();System.out.println("程序執行del方法,記錄日志.");}
}/*** @Author: EstellaQ* @Date: 2025/4/17 17:39* @Description: 代理模式測試**/
public class ProxyPattern {public static void main(String[] args) {DateService service = new DateServiceProxy();service.add();service.del();}
}
動態代理?
????????動態代理可以幫助我們僅僅在需要的時候再創建代理類,減少資源浪費,此外由于動態代理是一個模板的形式,也可以減少程序的代碼量,例如在靜態代碼示例中,我們在每個方法中加入System.out.println("程序執行***方法,記錄日志.");,當業務方法非常多時,我們也得為每個業務方法加上記錄日志的語句,而動態代理中將方法統一管理,無論幾個業務方法都只需要一條記錄語句即可實現,具體請看代碼。
/*** @Author: EstellaQ* @Date: 2025/4/17 17:48* @Description: 動態代理的代理類**/
public class ProxyInvocationHandler implements InvocationHandler {private DateService service;public ProxyInvocationHandler(DateService service) {this.service = service;}public Object getDateServiceProxy() {return Proxy.newProxyInstance(this.getClass().getClassLoader(), service.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {var result = method.invoke(service, args); // 讓service調用方法,方法返回值System.out.println(proxy.getClass().getName() + "代理類執行" + method.getName() + "方法,返回" + result + ",記錄日志!");return result;}
}/*** @Author: EstellaQ* @Date: 2025/4/17 17:39* @Description: 代理模式測試**/
public class ProxyPattern {public static void main(String[] args) {
//靜態代理
// DateService service = new DateServiceProxy();
// service.add();
// service.del();
//動態代理DateService serviceA = new DateServiceImplA();DateService serviceProxy = (DateService) new ProxyInvocationHandler(serviceA).getDateServiceProxy();serviceProxy.add();serviceProxy.del();}
}
七、?策略模式
????????該模式定義了一系列算法,并將每個算法封裝起來,使它們可以相互替換,且算法的變化不會影響使用算法的客戶。策略模式屬于對象行為模式,它通過對算法進行封裝,把使用算法的責任和算法的實現分割開來,并委派給不同的對象對這些算法進行管理。? 我認為跟工廠模式的思想很相似? ??
角色組成:??
抽象策略(Strategy)類
具體策略(Concrete Strategy)類
環境(Context)類
/*** @Author: EstellaQ* @Date: 2025/4/17 18:04* @Description: 抽象算法的策略類,定義所有支持的算法的公共接口**/
public interface Strategy {/*** 算法方法*/public void AlgorithmInterface();
}/*** @Author: EstellaQ* @Date: 2025/4/17 18:04* @Description: 策略實現類A**/
public class ConcreteStrategyA implements Strategy{@Overridepublic void AlgorithmInterface() {System.out.println("算法A的實現");}
}/*** @Author: EstellaQ* @Date: 2025/4/17 18:04* @Description: 策略實現類B**/
public class ConcreteStrategyB implements Strategy{@Overridepublic void AlgorithmInterface() {System.out.println("算法B的實現");}
}/*** @Author: EstellaQ* @Date: 2025/4/17 18:04* @Description: 策略實現類C**/
public class ConcreteStrategyC implements Strategy{@Overridepublic void AlgorithmInterface() {System.out.println("算法C的實現");}
}/*** @Author: EstellaQ* @Date: 2025/4/17 18:06* @Description: 上下文,維護一個對策略類對象的引用**/
public class Context {private Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}public void contextInterface(){strategy.AlgorithmInterface();}
}/*** @Author: EstellaQ* @Date: 2025/4/17 18:03* @Description: 策略模式的測試類**/
public class StrategyPattern {public static void main(String[] args) {Context context;context = new Context(new ConcreteStrategyA());context.contextInterface();context = new Context(new ConcreteStrategyB());context.contextInterface();context = new Context(new ConcreteStrategyC());context.contextInterface();}
}
JDK 中的應用:
- java.util.Comparator 是典型的策略模式。
Spring 中的應用:
- 事務管理(TransactionManager),支持編程式和聲明式事務。
八、?觀察者模式
????????觀察者模式是一種行為型設計模式,它定義了一種一對多的依賴關系,當一個對象的狀態發生改變時,其所有依賴者都會收到通知并自動更新。
角色組成:
- 主題(Subject):也稱為被觀察者或可觀察者,它是具有狀態的對象,并維護著一個觀察者列表。主題提供了添加、刪除和通知觀察者的方法。
- 觀察者(Observer):觀察者是接收主題通知的對象。觀察者需要實現一個更新方法,當收到主題的通知時,調用該方法進行更新操作。
- 具體主題(Concrete Subject):具體主題是主題的具體實現類。它維護著觀察者列表,并在狀態發生改變時通知觀察者。
- 具體觀察者(Concrete Observer):具體觀察者是觀察者的具體實現類。它實現了更新方法,定義了在收到主題通知時需要執行的具體操作。
/*** @Author: EstellaQ* @Date: 2025/4/17 18:42* @Description: 主題類,被觀察者**/
public class Subject {private List<Observer> observers = new ArrayList<Observer>();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();}}
}/*** @Author: EstellaQ* @Date: 2025/4/17 18:43* @Description: 被通知者的抽象類**/
public abstract class Observer {protected Subject subject;public abstract void update();}/*** @Author: EstellaQ* @Date: 2025/4/17 18:46* @Description: 被通知者的實現類**/
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() ) );}
}/*** @Author: EstellaQ* @Date: 2025/4/17 18:46* @Description: 被通知者的實現類**/
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() ) );}
}/*** @Author: EstellaQ* @Date: 2025/4/17 18:46* @Description: 被通知者的實現類**/
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() ) );}
}/*** @Author: EstellaQ* @Date: 2025/4/17 18:48* @Description: 觀察者模式測試**/
public class ObserverPattern {public static void main(String[] args) {Subject subject = new Subject();new HexaObserver(subject);new OctalObserver(subject);new BinaryObserver(subject);System.out.println("First state change: 15");subject.setState(15);System.out.println("Second state change: 10");subject.setState(10);}
}
JDK 中的應用:
- java.util.Observer 和 java.util.Observable
- javax.swing.event.ChangeListener
Spring 中的應用:
- ApplicationEvent 和 ApplicationListener 是典型實現。