一、概述
Java設(shè)計(jì)模式是Java程序設(shè)計(jì)中一種重要的最佳實(shí)踐,它提供了一種框架和結(jié)構(gòu),可以幫助開發(fā)者更好地理解和設(shè)計(jì)復(fù)雜的系統(tǒng)。設(shè)計(jì)模式不僅僅是一種語法規(guī)則,更是一種思想和方法論,它能夠幫助開發(fā)者更好地分析、設(shè)計(jì)和實(shí)現(xiàn)軟件系統(tǒng)。
設(shè)計(jì)模式的概念最早由GOF( Gang of Four)在1994年出版的《設(shè)計(jì)模式:可復(fù)用的面向?qū)ο筌浖O(shè)計(jì)》一書中提出。這本書中介紹了23種經(jīng)典的設(shè)計(jì)模式,這些設(shè)計(jì)模式是根據(jù)面向?qū)ο缶幊痰脑瓌t和最佳實(shí)踐總結(jié)出來的,旨在幫助開發(fā)者更好地設(shè)計(jì)和實(shí)現(xiàn)可擴(kuò)展、可維護(hù)和可重用的軟件系統(tǒng)。
本文將介紹Java設(shè)計(jì)模式的基本概念、特點(diǎn)和分類,并通過具體的示例來解釋不同類型的設(shè)計(jì)模式。
二、設(shè)計(jì)模式的定義和分類
設(shè)計(jì)模式是一種經(jīng)過驗(yàn)證的最佳實(shí)踐,用于解決軟件開發(fā)中常見的重復(fù)出現(xiàn)的問題。它提供了一種框架和結(jié)構(gòu),可以幫助開發(fā)者更好地設(shè)計(jì)和實(shí)現(xiàn)軟件系統(tǒng)。
設(shè)計(jì)模式通常被分為三種類型:創(chuàng)建型模式
、結(jié)構(gòu)型模式
和行為型模式
。
1.1、創(chuàng)建型模式
創(chuàng)建型模式關(guān)注對(duì)象創(chuàng)建的方式,主要解決對(duì)象創(chuàng)建的復(fù)雜性問題。以下是一些常見的創(chuàng)建型模式:
1.1.1、單例模式:確保只有一個(gè)特定類型的對(duì)象實(shí)例。
以下是一個(gè)簡(jiǎn)單的 Java 單例模式的實(shí)現(xiàn):
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
在這個(gè)實(shí)現(xiàn)中,我們使用一個(gè)靜態(tài)變量 instance 來保存單例對(duì)象。構(gòu)造函數(shù)是私有的,因此無法從外部創(chuàng)建實(shí)例。getInstance() 方法是公共的,并且返回單例對(duì)象。如果單例對(duì)象尚未創(chuàng)建,則會(huì)創(chuàng)建一個(gè)新的實(shí)例并將其存儲(chǔ)在 instance 變量中。由于 getInstance() 方法是同步的,因此它確保了在多線程環(huán)境中只有一個(gè)線程可以創(chuàng)建或獲取單例對(duì)象。
以下是另一種更優(yōu)雅的 Java 單例模式的實(shí)現(xiàn),使用了雙重檢查鎖定(double-checked locking):
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
在這個(gè)實(shí)現(xiàn)中,我們使用了雙重檢查鎖定來確保只有在第一次調(diào)用 getInstance() 方法時(shí)才會(huì)創(chuàng)建單例對(duì)象。在第一次檢查 instance 是否為 null 時(shí),沒有同步,因此只有單個(gè)線程可以進(jìn)入同步塊并創(chuàng)建單例對(duì)象。這樣可以避免在每次調(diào)用 getInstance() 方法時(shí)都進(jìn)行同步,從而提高性能。但是,需要注意的是,如果單例對(duì)象的創(chuàng)建非常耗時(shí)或需要執(zhí)行一些耗時(shí)的初始化操作,那么這個(gè)實(shí)現(xiàn)可能會(huì)導(dǎo)致性能問題。
1.1.2、原型模式:通過復(fù)制對(duì)象來創(chuàng)建新對(duì)象。
在Java中,可以通過實(shí)現(xiàn) Cloneable 接口并重寫 clone() 方法來使用原型模式。以下是一個(gè)簡(jiǎn)單的示例:
public class Circle implements Cloneable {
private int x;
private int y;
private int radius;
public Circle(int x, int y, int radius) {
this.x = x;
this.y = y;
this.radius = radius;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getRadius() {
return radius;
}
@Override
public Object clone() throws CloneNotSupportedException {
Circle circle = (Circle) super.clone();
return circle;
}
}
在上面的示例中,Circle 類實(shí)現(xiàn)了 Cloneable 接口并重寫了 clone() 方法。這個(gè)方法返回一個(gè)與原始對(duì)象具有相同值的新對(duì)象。需要注意的是,如果對(duì)象中有引用類型的成員變量,這些成員變量也需要使用同樣的方式進(jìn)行克隆。
1.1.4、工廠模式:通過工廠方法來創(chuàng)建對(duì)象,而不是直接實(shí)例化對(duì)象。
在工廠模式中,我們創(chuàng)建對(duì)象時(shí)不會(huì)直接使用 new 操作符,而是通過調(diào)用一個(gè)工廠方法來創(chuàng)建對(duì)象。這個(gè)工廠方法通常是一個(gè)靜態(tài)方法,它返回一個(gè)實(shí)現(xiàn)了特定接口或繼承了特定類的對(duì)象。
以下是一個(gè)簡(jiǎn)單的示例:
public interface Shape {
void draw();
}
public class Circle implements Shape {
public void draw() {
System.out.println("Circle draw method");
}
}
public class Rectangle implements Shape {
public void draw() {
System.out.println("Rectangle draw method");
}
}
public class ShapeFactory {
public static Shape getShape(String shapeType) {
if ("circle".equals(shapeType)) {
return new Circle();
} else if ("rectangle".equals(shapeType)) {
return new Rectangle();
}
return null;
}
}
在上面的示例中,我們定義了一個(gè) Shape 接口和兩個(gè)實(shí)現(xiàn)了 Shape 接口的類:Circle 和 Rectangle。我們還定義了一個(gè) ShapeFactory 類,它提供了一個(gè)靜態(tài)方法 getShape,該方法接受一個(gè)字符串參數(shù) shapeType,并根據(jù)該參數(shù)創(chuàng)建相應(yīng)的 Shape 對(duì)象。
使用工廠模式的好處是,我們可以在運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建不同類型的對(duì)象,而不需要在代碼中硬編碼它們。此外,工廠模式還可以幫助我們實(shí)現(xiàn)依賴注入和單元測(cè)試等其他功能。
1.1.5、建造者模式:通過逐步構(gòu)建對(duì)象來創(chuàng)建復(fù)雜對(duì)象。
在建造者模式中,我們創(chuàng)建對(duì)象時(shí)不會(huì)直接使用 new 操作符來創(chuàng)建對(duì)象,而是通過一系列的建造方法來逐步構(gòu)建對(duì)象。建造者模式通常用于創(chuàng)建復(fù)雜的對(duì)象,尤其是那些具有很多屬性并且這些屬性的初始化依賴于其他屬性的情況。
以下是一個(gè)簡(jiǎn)單的示例:
public class Car {
private String color;
private String model;
private int year;
public Car(Builder builder) {
this.color = builder.color;
this.model = builder.model;
this.year = builder.year;
}
public void drive() {
System.out.println("Driving " + this.color + " " + this.model + " car");
}
}
public class CarBuilder {
private String color;
private String model;
private int year;
public CarBuilder setColor(String color) {
this.color = color;
return this;
}
public CarBuilder setModel(String model) {
this.model = model;
return this;
}
public CarBuilder setYear(int year) {
this.year = year;
return this;
}
public Car build() {
return new Car(this);
}
}
在上面的示例中,我們定義了一個(gè) Car 類和一個(gè) CarBuilder 類。Car 類具有三個(gè)屬性:color、model 和 year。CarBuilder 類提供了設(shè)置這些屬性的方法,并且還有一個(gè) build 方法,該方法返回一個(gè) Car 對(duì)象。通過使用 CarBuilder,我們可以逐步構(gòu)建 Car 對(duì)象,而不需要在代碼中硬編碼它們。
1.1.6、抽象工廠模式:創(chuàng)建一組相關(guān)對(duì)象,并為其提供接口。
在抽象工廠模式中,我們定義了一個(gè)抽象的工廠接口,該接口聲明了一組創(chuàng)建對(duì)象的方法。然后,我們定義了多個(gè)實(shí)現(xiàn)該接口的具體工廠類,每個(gè)工廠類都提供了特定于該主題的對(duì)象。
以下是一個(gè)簡(jiǎn)單的示例:
public interface Shape {
void draw();
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing Circle");
}
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing Rectangle");
}
}
public interface ShapeFactory {
Shape getShape();
}
public class CircleFactory implements ShapeFactory {
@Override
public Circle getShape() {
return new Circle();
}
}
public class RectangleFactory implements ShapeFactory {
@Override
public Rectangle getShape() {
return new Rectangle();
}
}
在上面的示例中,我們定義了一個(gè)抽象的 Shape 接口和兩個(gè)實(shí)現(xiàn)該接口的具體類:Circle 和 Rectangle。我們還定義了一個(gè)抽象的 ShapeFactory 接口,它聲明了一個(gè) getShape 方法。然后,我們定義了兩個(gè)具體工廠類:CircleFactory 和 RectangleFactory,它們實(shí)現(xiàn)了 ShapeFactory 接口,并提供了特定于該主題的 Shape 對(duì)象。
在使用抽象工廠模式時(shí),我們可以創(chuàng)建不同的工廠對(duì)象來獲取不同類型的對(duì)象。例如,我們可以創(chuàng)建一個(gè) CircleFactory 對(duì)象來獲取 Circle 對(duì)象,或者創(chuàng)建一個(gè) RectangleFactory 對(duì)象來獲取 Rectangle 對(duì)象。這樣,我們就可以在不指定具體類的情況下創(chuàng)建不同類型的對(duì)象。
1.2、結(jié)構(gòu)型模式
結(jié)構(gòu)型模式關(guān)注對(duì)象之間的組合關(guān)系,主要解決如何組合對(duì)象以形成更大的結(jié)構(gòu)。以下是一些常見的結(jié)構(gòu)型模式:
1.2.1、適配器模式:將一個(gè)類的接口轉(zhuǎn)換成另一個(gè)客戶端所期望的接口形式。
在適配器模式中,我們定義了一個(gè)適配器類,該類實(shí)現(xiàn)了目標(biāo)接口,并將不兼容的接口轉(zhuǎn)換為兼容的接口。通常,適配器類會(huì)接收一個(gè)實(shí)現(xiàn)了不兼容接口的對(duì)象,并將其轉(zhuǎn)換為另一個(gè)實(shí)現(xiàn)了目標(biāo)接口的對(duì)象。
以下是一個(gè)簡(jiǎn)單的示例:
public interface Target {
void doSomething();
}
public class Adaptee implements Target {
@Override
public void doSomething() {
System.out.println("Adaptee's doSomething method");
}
}
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void doSomething() {
adaptee.doSomething();
}
}
在上面的示例中,我們定義了一個(gè) Target 接口,以及一個(gè)實(shí)現(xiàn)了該接口的 Adaptee 類。我們還定義了一個(gè)適配器類 Adapter,該類實(shí)現(xiàn)了 Target 接口,并將 Adaptee 類的 doSomething 方法轉(zhuǎn)換為 Target 接口的 doSomething 方法。
在使用適配器模式時(shí),我們可以創(chuàng)建一個(gè) Adaptee 對(duì)象,并將其傳遞給 Adapter 構(gòu)造函數(shù)。然后,我們可以使用 Adapter 對(duì)象來調(diào)用 Target 接口的 doSomething 方法,而實(shí)際執(zhí)行的是 Adaptee 類的 doSomething 方法。
適配器模式提供了一種靈活的方式來處理不兼容的接口,它可以將不同的接口集成到同一個(gè)系統(tǒng)中,并使它們能夠相互協(xié)作。
1.2.2、橋接模式:將一個(gè)復(fù)雜的類層次結(jié)構(gòu)分解為多個(gè)簡(jiǎn)單的接口,以便于獨(dú)立升級(jí)和擴(kuò)展。
Java 橋接模式提供了一種方式來將一個(gè)類的接口與另一個(gè)不相關(guān)的接口關(guān)聯(lián)起來。
在橋接模式中,我們定義了一個(gè)橋接類,該類將一個(gè)類的接口與另一個(gè)不相關(guān)的接口關(guān)聯(lián)起來。通常,橋接類會(huì)包含一個(gè)實(shí)現(xiàn)了不相關(guān)接口的對(duì)象,并將該對(duì)象的操作轉(zhuǎn)換為原始接口的操作。
以下是一個(gè)簡(jiǎn)單的示例:
public interface Shape {
void draw();
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing Circle");
}
}
public interface Color {
void fill();
}
public class Red implements Color {
@Override
public void fill() {
System.out.println("filling with red color");
}
}
public class Bridge implements Shape, Color {
private Circle circle;
private Red color;
public Bridge(Circle circle, Red color) {
this.circle = circle;
this.color = color;
}
@Override
public void draw() {
circle.draw();
}
@Override
public void fill() {
color.fill();
}
}
在上面的示例中,我們定義了兩個(gè)接口,Shape 和 Color,分別表示圖形和顏色。我們還定義了 Circle 和 Red 類,分別實(shí)現(xiàn)了 Shape 和 Color 接口。最后,我們定義了一個(gè) Bridge 類,該類實(shí)現(xiàn)了 Shape 和 Color 接口,并將 Circle 和 Red 類的操作轉(zhuǎn)換為這兩個(gè)接口的操作。
在使用橋接模式時(shí),我們可以創(chuàng)建一個(gè) Circle 對(duì)象和一個(gè) Red 對(duì)象,并將它們傳遞給 Bridge 構(gòu)造函數(shù)。然后,我們可以使用 Bridge 對(duì)象來調(diào)用 Shape 和 Color 接口的方法,而實(shí)際執(zhí)行的是 Circle 和 Red 類的操作。
橋接模式提供了一種靈活的方式來將不同的接口關(guān)聯(lián)起來,它可以將不相關(guān)的接口集成到同一個(gè)對(duì)象中,并使它們能夠相互協(xié)作。
1.2.3、組合模式:將一組相關(guān)對(duì)象組合成一個(gè)樹形結(jié)構(gòu),以便于客戶端以統(tǒng)一的方式處理對(duì)象。
Java 組合模式提供了一種方式來組合多個(gè)對(duì)象,從而形成一個(gè)樹形結(jié)構(gòu),并可以遞歸地調(diào)用這些對(duì)象的操作。
在組合模式中,我們定義了一個(gè)抽象的節(jié)點(diǎn)類,該節(jié)點(diǎn)類包含了子節(jié)點(diǎn)的引用。然后,我們定義了兩個(gè)具體的節(jié)點(diǎn)類,一個(gè)是葉節(jié)點(diǎn),另一個(gè)是組合節(jié)點(diǎn)。葉節(jié)點(diǎn)表示樹的末端,它沒有子節(jié)點(diǎn)。組合節(jié)點(diǎn)表示樹的分支,它可以包含多個(gè)子節(jié)點(diǎn)。
以下是一個(gè)簡(jiǎn)單的示例:
public abstract class Component {
protected Component left;
protected Component right;
public Component(Component left, Component right) {
this.left = left;
this.right = right;
}
public abstract void operation();
}
public class Leaf extends Component {
private String name;
public Leaf(String name) {
this.name = name;
}
@Override
public void operation() {
System.out.println("Leaf " + name + ": operation()");
}
}
public class Composite extends Component {
private List<Component> children;
public Composite() {
children = new ArrayList<>();
}
public void add(Component component) {
children.add(component);
}
@Override
public void operation() {
for (Component child : children) {
child.operation();
}
}
}
在上面的示例中,我們定義了一個(gè)抽象的節(jié)點(diǎn)類 Component,它包含了左右子節(jié)點(diǎn)的引用。然后,我們定義了兩個(gè)具體的節(jié)點(diǎn)類,一個(gè)是葉節(jié)點(diǎn) Leaf,另一個(gè)是組合節(jié)點(diǎn) Composite。葉節(jié)點(diǎn)表示樹的末端,它沒有子節(jié)點(diǎn)。組合節(jié)點(diǎn)表示樹的分支,它可以包含多個(gè)子節(jié)點(diǎn)。
在使用組合模式時(shí),我們可以創(chuàng)建一個(gè)樹形結(jié)構(gòu),每個(gè)節(jié)點(diǎn)可以是葉節(jié)點(diǎn)或組合節(jié)點(diǎn)。組合節(jié)點(diǎn)可以遞歸地調(diào)用其子節(jié)點(diǎn)的操作。例如,我們可以創(chuàng)建一個(gè)包含多個(gè)葉節(jié)點(diǎn)和組合節(jié)點(diǎn)的樹,并調(diào)用根節(jié)點(diǎn)的 operation() 方法,該方法將遞歸地調(diào)用所有子節(jié)點(diǎn)的 operation() 方法。
1.2.4、裝飾器模式:動(dòng)態(tài)地給一個(gè)對(duì)象添加額外的職責(zé),同時(shí)保持對(duì)象的接口不變。
Java 裝飾器模式提供了一種方式來動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。這通過創(chuàng)建一個(gè)包裝對(duì)象,它包裝了原始對(duì)象并提供一個(gè)新的接口,經(jīng)常用于改變一個(gè)或多個(gè)類的行為或?yàn)槠涮砑有碌男袨椤?/p>
裝飾器模式包含以下四個(gè)角色:
- Component:定義一個(gè)接口,這個(gè)接口表示可以被裝飾的行為。
- ConcreteComponent:實(shí)現(xiàn) Component 接口,表示需要被裝飾的具體對(duì)象。
- Decorator:繼承 Component 接口,并且包含一個(gè)對(duì) ConcreteComponent 的引用。Decorator 提供了一種方法來將自身添加到被裝飾的對(duì)象的引用中。
- ConcreteDecorator:實(shí)現(xiàn) Component 接口,并添加額外的功能。在需要的時(shí)候,可以調(diào)用 ConcreteComponent 的方法。
下面是一個(gè)簡(jiǎn)單的 Java 示例代碼:
// Component
interface Coffee {
double getCost();
String getIngredients();
}
// ConcreteComponent
class SimpleCoffee implements Coffee {
public double getCost() {
return 1;
}
public String getIngredients() {
return "Coffee";
}
}
// Decorator
abstract class CoffeeDecorator implements Coffee {
protected Coffee decoratedCoffee;
public CoffeeDecorator(Coffee c) {
this.decoratedCoffee = c;
}
public double getCost() {
return decoratedCoffee.getCost();
}
public String getIngredients() {
return decoratedCoffee.getIngredients();
}
}
// ConcreteDecorator A
class WhippedCoffee extends CoffeeDecorator {
public WhippedCoffee(Coffee c) {
super(c);
}
public double getCost() {
return decoratedCoffee.getCost() + 0.5;
}
public String getIngredients() {
return decoratedCoffee.getIngredients() + ", Whipped Cream";
}
}
// ConcreteDecorator B
class MochaCoffee extends CoffeeDecorator {
public MochaCoffee(Coffee c) {
super(c);
}
public double getCost() {
return decoratedCoffee.getCost() + 1;
}
public String getIngredients() {
return decoratedCoffee.getIngredients() + ", Mocha";
}
}
在這個(gè)示例中,我們首先定義了一個(gè) Coffee 接口和它的實(shí)現(xiàn)類 SimpleCoffee。然后,我們創(chuàng)建了一個(gè)抽象的 Decorator 類,它實(shí)現(xiàn)了 Coffee 接口并包含一個(gè)對(duì)被裝飾對(duì)象的引用。接下來,我們創(chuàng)建了兩個(gè)具體的裝飾器類 WhippedCoffee 和 MochaCoffee,它們分別添加了 “Whipped Cream” 和 “Mocha” 的成分和價(jià)格。最后,我們可以使用這些裝飾器來動(dòng)態(tài)地給咖啡添加額外的職責(zé)。
1.2.5、外觀模式:為子系統(tǒng)提供單一的入口點(diǎn),簡(jiǎn)化子系統(tǒng)的使用。
外觀模式(Facade Pattern)提供了一個(gè)簡(jiǎn)化的接口,將一些復(fù)雜的子系統(tǒng)或類的使用方式變得簡(jiǎn)單。外觀模式的主要目的是簡(jiǎn)化接口,以便客戶端代碼能夠更方便地使用子系統(tǒng)或類。
在 Java 中,外觀模式通常使用類來實(shí)現(xiàn)。外觀類提供了一些簡(jiǎn)單的方法,這些方法將客戶端代碼與子系統(tǒng)或類的復(fù)雜實(shí)現(xiàn)隔離開來。外觀類通常只暴露子系統(tǒng)或類的一小部分功能,并且隱藏了內(nèi)部實(shí)現(xiàn)的細(xì)節(jié)。
下面是一個(gè)簡(jiǎn)單的 Java 代碼示例,演示了外觀模式的使用:
public class Facade {
private SubSystem1 subSystem1;
private SubSystem2 subSystem2;
public Facade() {
subSystem1 = new SubSystem1();
subSystem2 = new SubSystem2();
}
public void simplifiedMethod() {
subSystem1.complexMethod1();
subSystem2.complexMethod2();
}
}
public class SubSystem1 {
public void complexMethod1() {
// complex implementation of method 1
}
}
public class SubSystem2 {
public void complexMethod2() {
// complex implementation of method 2
}
}
在上面的代碼中,F(xiàn)acade 類是外觀類,它簡(jiǎn)化了 SubSystem1 和 SubSystem2 的使用方式。Facade 類只提供了一個(gè) simplifiedMethod() 方法,該方法調(diào)用了 SubSystem1 和 SubSystem2 的復(fù)雜方法。這樣,客戶端代碼只需要調(diào)用 Facade 類的 simplifiedMethod() 方法,而不需要直接調(diào)用 SubSystem1 和 SubSystem2 的復(fù)雜方法。
使用外觀模式可以降低客戶端代碼與子系統(tǒng)或類的耦合度,提高了代碼的可維護(hù)性和可讀性。同時(shí),外觀模式還可以隱藏子系統(tǒng)或類的內(nèi)部實(shí)現(xiàn)細(xì)節(jié),提高了系統(tǒng)的安全性。
1.2.6、享元模式:通過共享對(duì)象來減少系統(tǒng)中的對(duì)象數(shù)量,以降低系統(tǒng)的內(nèi)存占用。
享元模式用于減少創(chuàng)建對(duì)象的數(shù)量,以便降低內(nèi)存消耗和提高性能。享元模式通過共享對(duì)象來實(shí)現(xiàn)這一目標(biāo),使得多個(gè)客戶端可以共享同一個(gè)對(duì)象,而不是為每個(gè)客戶端創(chuàng)建新的對(duì)象。
享元模式主要適用于以下情況:
- 對(duì)象創(chuàng)建成本較高:如果對(duì)象的創(chuàng)建成本較高,例如需要消耗大量的內(nèi)存或網(wǎng)絡(luò)帶寬,那么使用享元模式可以降低對(duì)象的創(chuàng)建和銷毀開銷。
- 對(duì)象數(shù)量可能非常大:如果需要?jiǎng)?chuàng)建的對(duì)象數(shù)量可能非常大,例如在圖形渲染或數(shù)據(jù)處理中,使用享元模式可以避免大量的對(duì)象創(chuàng)建,從而減少內(nèi)存消耗。
在 Java 中,享元模式通常使用一個(gè)享元工廠類來管理共享對(duì)象。享元工廠類負(fù)責(zé)創(chuàng)建和管理共享對(duì)象,并確保多個(gè)客戶端共享同一個(gè)對(duì)象。
下面是一個(gè)簡(jiǎn)單的 Java 代碼示例,演示了享元模式的使用:
import java.util.HashMap;
import java.util.Map;
public class FlyweightFactory {
private Map<String, Flyweight> flyweights = new HashMap<>();
public synchronized Flyweight getFlyweight(String key) {
if (!flyweights.containsKey(key)) {
Flyweight flyweight = new Flyweight(key);
flyweights.put(key, flyweight);
}
return flyweights.get(key);
}
}
public abstract class Flyweight {
protected String key;
public Flyweight(String key) {
this.key = key;
}
public abstract void operation(int x, int y);
}
public class ConcreteFlyweight1 extends Flyweight {
public ConcreteFlyweight1(String key) {
super(key);
}
@Override
public void operation(int x, int y) {
// implementation of operation for ConcreteFlyweight1
}
}
public class ConcreteFlyweight2 extends Flyweight {
public ConcreteFlyweight2(String key) {
super(key);
}
@Override
public void operation(int x, int y) {
// implementation of operation for ConcreteFlyweight2
}
}
在上面的代碼中,F(xiàn)lyweightFactory 類是享元工廠類,它負(fù)責(zé)創(chuàng)建和管理共享對(duì)象。Flyweight 是一個(gè)抽象類,表示享元對(duì)象。ConcreteFlyweight1 和 ConcreteFlyweight2 是具體的享元實(shí)現(xiàn)類。每個(gè)享元實(shí)現(xiàn)類對(duì)應(yīng)不同的操作。通過調(diào)用 FlyweightFactory 的 getFlyweight() 方法,可以獲取共享的享元對(duì)象。在獲取對(duì)象時(shí),如果該對(duì)象不存在,則創(chuàng)建一個(gè)新的對(duì)象并將其添加到共享對(duì)象池中。如果該對(duì)象已經(jīng)存在,則直接返回已經(jīng)存在的對(duì)象。通過這種方式,多個(gè)客戶端可以共享同一個(gè)享元對(duì)象,從而減少了對(duì)象的創(chuàng)建和銷毀開銷。
1.2.7、代理模式:通過代理來控制對(duì)另一個(gè)對(duì)象的訪問。
代理模式是提供了一種將實(shí)際操作隱藏在代理對(duì)象之后的機(jī)制。代理模式通常用于控制對(duì)對(duì)象的訪問,提供額外的功能或者修改對(duì)象的行為。
代理模式包括以下兩種類型:
- 靜態(tài)代理:靜態(tài)代理是指在編譯期間代理類和被代理類之間的關(guān)系就已經(jīng)確定。代理類需要實(shí)現(xiàn)與被代理類相同的接口,并在代理類中調(diào)用被代理類的方法。在調(diào)用過程中,可以執(zhí)行額外的操作。
- 動(dòng)態(tài)代理:動(dòng)態(tài)代理是指在運(yùn)行時(shí)創(chuàng)建代理類。Java 中的動(dòng)態(tài)代理主要通過 java.lang.reflect 包中的 Proxy 類和 InvocationHandler 接口實(shí)現(xiàn)。動(dòng)態(tài)代理允許在運(yùn)行時(shí)動(dòng)態(tài)地創(chuàng)建代理類,并且可以實(shí)現(xiàn)對(duì)被代理對(duì)象的增強(qiáng)和修改。
下面是一個(gè)簡(jiǎn)單的靜態(tài)代理的示例:
public interface Shape {
void draw();
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle...");
}
}
public class RectangleProxy implements Shape {
private Rectangle rectangle;
public RectangleProxy(Rectangle rectangle) {
this.rectangle = rectangle;
}
@Override
public void draw() {
System.out.println("Drawing a rectangle...");
rectangle.draw();
System.out.println("Drawing a rectangle...done");
}
}
public class Main {
public static void main(String[] args) {
Shape rectangle = new Rectangle();
Shape rectangleProxy = new RectangleProxy(rectangle);
rectangleProxy.draw();
}
}
在上面的示例中,Rectangle 是被代理類,RectangleProxy 是代理類。RectangleProxy 實(shí)現(xiàn)了與 Rectangle 相同的接口 Shape,并且在 draw() 方法中調(diào)用了 Rectangle 的 draw() 方法。這樣,在調(diào)用 rectangleProxy.draw() 時(shí),額外的操作也會(huì)被執(zhí)行。
需要注意的是,靜態(tài)代理需要在編譯期間創(chuàng)建代理類和被代理類的關(guān)系,而動(dòng)態(tài)代理可以在運(yùn)行時(shí)動(dòng)態(tài)地創(chuàng)建代理類和被代理類的關(guān)系。動(dòng)態(tài)代理的靈活性和靈活性使其成為實(shí)際應(yīng)用程序中的常用技術(shù)。
1.3、行為型模式
行為型模式關(guān)注對(duì)象之間的交互關(guān)系,主要解決如何讓對(duì)象之間更好地協(xié)同工作。以下是一些常見的行為型模式:
1.3.1、策略模式:定義一系列可互換的算法,并將每個(gè)算法封裝起來,使它們可以相互替換。
策略模式是定義了一系列可以互相替換的算法,使得在運(yùn)行時(shí)可以根據(jù)情況選擇合適的算法。
策略模式包括以下組件:
- 策略(Strategy):定義了一系列的策略接口,每個(gè)策略接口表示一個(gè)具體的算法。策略類通常包含一些共同的行為和屬性。
- 具體策略(ConcreteStrategy):實(shí)現(xiàn)了策略接口,實(shí)現(xiàn)了具體的算法。每個(gè)具體策略類表示一個(gè)具體的算法。
- 環(huán)境(Context):持有策略對(duì)象的引用,并且使用策略對(duì)象的方法來執(zhí)行具體的操作。
下面是一個(gè)簡(jiǎn)單的示例代碼:
// 策略接口
public interface Strategy {
public void execute();
}
// 具體策略類1
public class ConcreteStrategy1 implements Strategy {
@Override
public void execute() {
System.out.println("ConcreteStrategy1 is executed.");
}
}
// 具體策略類2
public class ConcreteStrategy2 implements Strategy {
@Override
public void execute() {
System.out.println("ConcreteStrategy2 is executed.");
}
}
// 環(huán)境類
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void executeStrategy() {
strategy.execute();
}
}
// 測(cè)試代碼
public class Main {
public static void main(String[] args) {
Strategy strategy1 = new ConcreteStrategy1();
Context context1 = new Context(strategy1);
context1.executeStrategy(); // 輸出:ConcreteStrategy1 is executed.
Strategy strategy2 = new ConcreteStrategy2();
Context context2 = new Context(strategy2);
context2.executeStrategy(); // 輸出:ConcreteStrategy2 is executed.
}
}
在上面的示例中,Strategy 是一個(gè)策略接口,定義了一個(gè) execute() 方法。ConcreteStrategy1 和 ConcreteStrategy2 是具體的策略類,分別實(shí)現(xiàn)了 Strategy 接口,并重寫了 execute() 方法。Context 類持有一個(gè)策略對(duì)象的引用,并在 executeStrategy() 方法中調(diào)用了策略對(duì)象的 execute() 方法。在測(cè)試代碼中,我們可以根據(jù)需要選擇具體的策略對(duì)象來執(zhí)行操作。
1.3.2、觀察者模式:定義對(duì)象之間的依賴關(guān)系,當(dāng)一個(gè)對(duì)象發(fā)生改變時(shí),所有依賴于它的對(duì)象都會(huì)收到通知并自動(dòng)更新。
觀察者模式定義了一種一對(duì)多的依賴關(guān)系,使得當(dāng)一個(gè)對(duì)象(主題)的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象(觀察者)都能夠得到通知并自動(dòng)更新。
觀察者模式包括以下組件:
- 主題(Subject):維護(hù)一個(gè)觀察者列表,并定義了添加和刪除觀察者的方法。當(dāng)主題的狀態(tài)發(fā)生改變時(shí),它會(huì)自動(dòng)通知所有的觀察者。
- 觀察者(Observer):定義了一個(gè)更新方法,當(dāng)主題的狀態(tài)發(fā)生改變時(shí),該方法將被調(diào)用。
下面是一個(gè)簡(jiǎn)單的示例代碼:
// 主題接口
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// 具體主題類
public class ConcreteSubject implements Subject {
private ObserverList observers;
private int state;
public ConcreteSubject() {
observers = new ObserverList();
}
public void setState(int state) {
this.state = state;
notifyObservers();
}
@Override
public void registerObserver(Observer observer) {
observers.addObserver(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.removeObserver(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
// 觀察者接口
public interface Observer {
void update();
}
// 具體觀察者類1
public class ConcreteObserver1 implements Observer {
private int state;
@Override
public void update() {
state = ((ConcreteSubject) ((ObserverObject) subject).getSubject()).getState();
System.out.println("ConcreteObserver1 received state: " + state);
}
}
// 具體觀察者類2
public class ConcreteObserver2 implements Observer {
private int state;
@Override
public void update() {
state = ((ConcreteSubject) ((ObserverObject) subject).getSubject()).getState();
System.out.println("ConcreteObserver2 received state: " + state);
}
}
// 觀察者列表類
public class ObserverList {
private ArrayList<Observer> observers;
public ObserverList() {
observers = new ArrayList<Observer>();
}
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
}
1.3.3、模板方法模式:定義一個(gè)操作算法的骨架,將某些步驟的執(zhí)行延遲到子類中實(shí)現(xiàn)。
模板方法模式定義了一個(gè)操作的框架,將算法的步驟封裝到不同的抽象方法中,從而允許子類在不改變算法結(jié)構(gòu)的情況下重定義某些步驟的具體實(shí)現(xiàn)。
在 Java 中,模板方法模式通常使用繼承來實(shí)現(xiàn)。一個(gè)抽象類定義了算法的框架,包括一些抽象方法和一些具體方法。子類可以繼承這個(gè)抽象類,重定義抽象方法以提供自己的實(shí)現(xiàn),而具體方法則保留了與框架的接口一致的實(shí)現(xiàn)。
以下是一個(gè)簡(jiǎn)單的示例代碼,演示了模板方法模式的使用:
public abstract class Template {
public void templateMethod() {
step1();
System.out.println("Algorithm framework");
step2();
System.out.println("Algorithm framework");
step3();
}
public abstract void step1();
public abstract void step2();
public abstract void step3();
}
public class ConcreteTemplate extends Template {
@Override
public void step1() {
System.out.println("Concrete step 1");
}
@Override
public void step2() {
System.out.println("Concrete step 2");
}
@Override
public void step3() {
System.out.println("Concrete step 3");
}
}
在上面的代碼中,Template 是一個(gè)抽象類,定義了一個(gè)模板方法 templateMethod(),它包含了算法的框架。step1()、step2() 和 step3() 是抽象方法,子類需要提供具體的實(shí)現(xiàn)。ConcreteTemplate 是 Template 的一個(gè)子類,重定義了所有的抽象方法,提供了自己的實(shí)現(xiàn)。在 templateMethod() 中,算法的框架保持不變,但是每個(gè)步驟的具體實(shí)現(xiàn)都由子類提供。
使用模板方法模式的好處是它可以讓子類在不改變算法結(jié)構(gòu)的情況下重定義某些步驟的具體實(shí)現(xiàn)。這使得代碼更加靈活和可維護(hù)。同時(shí),模板方法模式還可以提高代碼的可重用性,因?yàn)樗惴ǖ目蚣芸梢栽诓煌淖宇愔兄貜?fù)使用。
1.3.4、狀態(tài)模式:將一個(gè)對(duì)象的狀態(tài)轉(zhuǎn)換細(xì)化為各個(gè)狀態(tài),每個(gè)狀態(tài)對(duì)應(yīng)一個(gè)類,實(shí)現(xiàn)狀態(tài)的轉(zhuǎn)換和特定狀態(tài)的邏輯。
狀態(tài)模式允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變其行為。狀態(tài)模式通過把狀態(tài)封裝到單獨(dú)的狀態(tài)類中來實(shí)現(xiàn)的,每個(gè)狀態(tài)類負(fù)責(zé)處理對(duì)應(yīng)的狀態(tài),并且可以有一個(gè)機(jī)會(huì)改變內(nèi)部狀態(tài)或者發(fā)出命令。
以下是一個(gè)簡(jiǎn)單的示例代碼,演示了狀態(tài)模式的使用:
public interface State {
void handle(Context context);
}
public class StateA implements State {
@Override
public void handle(Context context) {
System.out.println("StateA handled, context state: " + context.getState());
context.setState(new StateB());
}
}
public class StateB implements State {
@Override
public void handle(Context context) {
System.out.println("StateB handled, context state: " + context.getState());
context.setState(new StateA());
}
}
public class Context {
private State state;
private String stateData;
public Context(State initialState) {
this.state = initialState;
}
public void setState(State state) {
this.state = state;
}
public String getStateData() {
return stateData;
}
public void setStateData(String stateData) {
this.stateData = stateData;
}
public void request() {
state.handle(this);
}
}
在上面的代碼中,State 是一個(gè)接口,定義了一個(gè) handle() 方法。StateA 和 StateB 是實(shí)現(xiàn)了 State 接口的兩個(gè)具體狀態(tài)類,每個(gè)狀態(tài)類都有自己的 handle() 方法。Context 類保存了一個(gè)當(dāng)前狀態(tài)的引用,并有一個(gè) request() 方法來處理請(qǐng)求。當(dāng) Context 的 request() 方法被調(diào)用時(shí),當(dāng)前狀態(tài)會(huì)處理請(qǐng)求,并在處理結(jié)束后改變狀態(tài)。
使用狀態(tài)模式的好處是它可以讓一個(gè)對(duì)象根據(jù)其內(nèi)部狀態(tài)來改變其行為,并且可以將狀態(tài)封裝到單獨(dú)的狀態(tài)類中,使得代碼更加清晰和易于維護(hù)。同時(shí),狀態(tài)模式還可以提高代碼的可重用性,因?yàn)椴煌臓顟B(tài)類可以具有相似的行為。
1.3.5、命令模式:定義一個(gè)命令接口,通過接收命令對(duì)象來實(shí)現(xiàn)命令的執(zhí)行。
命令模式允許你將請(qǐng)求封裝為一個(gè)對(duì)象,從而使請(qǐng)求可以被取消,被記錄,或者被參數(shù)化。
以下是一個(gè)簡(jiǎn)單的示例代碼,演示了命令模式的使用:
public interface Command {
void execute();
}
public class ConcreteCommand implements Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.doSomething();
}
}
public interface Receiver {
void doSomething();
}
public class ConcreteReceiver implements Receiver {
@Override
public void doSomething() {
System.out.println("Receiver did something");
}
}
public classInvoker`public class Invoker {
private Command command;
public Invoker(Command command) {
this.command = command;
}
public void setCommand(Command command) {
this.command = command;
}
public void executeCommand() {
command.execute();
}
}
在上面的代碼中,Command 是一個(gè)抽象命令接口,定義了一個(gè) execute() 方法。ConcreteCommand 是一個(gè)具體命令類,實(shí)現(xiàn)了 Command 接口,并關(guān)聯(lián)了一個(gè) Receiver 對(duì)象。當(dāng)調(diào)用 execute() 方法時(shí),具體命令類會(huì)調(diào)用接收者的 doSomething() 方法。Receiver 是一個(gè)接收者接口,定義了一個(gè) doSomething() 方法。ConcreteReceiver 是一個(gè)具體接收者類,實(shí)現(xiàn)了 Receiver 接口,并實(shí)現(xiàn)了 doSomething() 方法。Invoker 是調(diào)用者接口,它持有對(duì)命令的引用,并調(diào)用命令的 execute() 方法來執(zhí)行請(qǐng)求。通過這種方式,調(diào)用者與具體命令的實(shí)現(xiàn)解耦,使得可以靈活地增加新的命令類,而不需要修改調(diào)用者的代碼。
1.3.6、迭代器模式:提供一種方法來順序訪問一個(gè)聚合對(duì)象的元素,而不暴露其底層表示。
迭代器模式提供了一種在集合對(duì)象中遍歷元素的標(biāo)準(zhǔn)方法。迭代器模式允許我們順序訪問一個(gè)聚合對(duì)象的元素,而不暴露其底層表示。
以下是一個(gè)簡(jiǎn)單的示例代碼,演示了迭代器模式的使用:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class IteratorExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Orange");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
System.out.println(item);
}
}
}
在上面的代碼中,我們創(chuàng)建了一個(gè) List 對(duì)象,并向其中添加了一些元素。然后,我們使用 iterator() 方法獲取了一個(gè)迭代器對(duì)象,并使用 hasNext() 方法檢查是否還有下一個(gè)元素。如果有,我們使用 next() 方法獲取下一個(gè)元素,并輸出到控制臺(tái)。通過這種方式,我們可以遍歷整個(gè)列表。
迭代器模式的主要優(yōu)點(diǎn)是它提供了一種統(tǒng)一的訪問聚合對(duì)象的方法,而不必關(guān)心底層表示。此外,迭代器模式還可以在遍歷過程中刪除元素,而不會(huì)導(dǎo)致 ConcurrentModificationException 異常。
1.3.7、訪問者模式:在不改變數(shù)據(jù)結(jié)構(gòu)的前提下增加新的操作,通過定義一個(gè)訪問者類來實(shí)現(xiàn)對(duì)數(shù)據(jù)的操作。
訪問者模式允許一個(gè)操作作用于一個(gè)對(duì)象結(jié)構(gòu)中的各個(gè)元素,而這個(gè)對(duì)象結(jié)構(gòu)可以是一個(gè)簡(jiǎn)單的數(shù)組,也可以是一個(gè)復(fù)雜的樹形結(jié)構(gòu)。訪問者模式主要解決的是一種數(shù)據(jù)結(jié)構(gòu)或者對(duì)象結(jié)構(gòu)中,數(shù)據(jù)類型復(fù)雜且變化多端的問題。
訪問者模式包含以下主要角色:
- 訪問者(Visitor):定義了一個(gè)訪問操作的方法,該方法接收一個(gè)元素對(duì)象作為參數(shù)。
被訪問對(duì)象(Element):提供訪問者所需的方法,一般該方法被稱為 accept。 - 具體元素類(ConcreteElement):實(shí)現(xiàn) Element 類,并接受訪問者的訪問,在訪問完畢后執(zhí)行一些具體的操作。
以下是一個(gè)簡(jiǎn)單的示例代碼,演示了訪問者模式的使用:
// 定義元素類
class ConcreteElementA {
private String name;
public ConcreteElementA(String name) {
this.name = name;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
class ConcreteElementB {
private String name;
public ConcreteElementB(String name) {
this.name = name;
}
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
// 定義訪問者接口
interface Visitor {
void visit(ConcreteElementA elementA);
void visit(ConcreteElementB elementB);
}
// 定義具體訪問者類
class ConcreteVisitor implements Visitor {
public void visit(ConcreteElementA elementA) {
System.out.println(elementA.name + " visited by ConcreteVisitor");
}
public void visit(ConcreteElementB elementB) {
System.out.println(elementB.name + " visited by ConcreteVisitor");
}
}
在上面的代碼中,我們定義了兩個(gè)元素類 ConcreteElementA 和 ConcreteElementB,它們都實(shí)現(xiàn)了 Element 類的 accept 方法。然后,我們定義了一個(gè)訪問者接口 Visitor,其中包含了兩個(gè)訪問方法分別對(duì)應(yīng)兩個(gè)元素類。最后,我們創(chuàng)建了一個(gè)具體的訪問者類 ConcreteVisitor,實(shí)現(xiàn)了 Visitor 接口中的方法。通過這種方式,我們可以對(duì)不同的元素類執(zhí)行不同的操作。
1.3.8、備忘錄模式:保存一個(gè)對(duì)象的內(nèi)部狀態(tài),并在需要時(shí)恢復(fù)該對(duì)象的狀態(tài)。
備忘錄模式提供了一種保存對(duì)象內(nèi)部狀態(tài)的機(jī)制,并在以后需要時(shí)能夠恢復(fù)這個(gè)狀態(tài)。它允許在不暴露對(duì)象內(nèi)部狀態(tài)的情況下保存和恢復(fù)對(duì)象的狀態(tài)。
在 Java 中,備忘錄模式可以使用以下步驟實(shí)現(xiàn):
定義一個(gè)備忘錄類(Memento),該類包含了原始對(duì)象(Originator)的內(nèi)部狀態(tài)。
public class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
定義一個(gè)原始對(duì)象(Originator),該對(duì)象允許其他對(duì)象保存和恢復(fù)其內(nèi)部狀態(tài)。
public class Originator {
private String state;
public Originator(String state) {
this.state = state;
}
public String getState() {
return state;
}
public Memento getMemento() {
return new Memento(state);
}
public void restoreFromMemento(Memento memento) {
this.state = memento.getState();
}
}
定義一個(gè)管理者類(Caretaker),該類負(fù)責(zé)保存和恢復(fù)原始對(duì)象的備忘錄。
public class Caretaker {
private Memento memento;
public Caretaker(Memento memento) {
this.memento = memento;
}
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
在上述代碼中,Originator 類的 getMemento() 方法用于創(chuàng)建一個(gè)新的備忘錄,restoreFromMemento() 方法用于從備忘錄中恢復(fù)狀態(tài)。Caretaker 類負(fù)責(zé)保存和恢復(fù)備忘錄。使用備忘錄模式時(shí),需要先保存原始對(duì)象的當(dāng)前狀態(tài),然后在需要時(shí)恢復(fù)該狀態(tài)。
1.3.9、中介者模式:將一組對(duì)象之間的交互封裝到一個(gè)中介者對(duì)象中,降低對(duì)象之間的耦合性。
中介者模式提供了一種將對(duì)象之間的交互集中管理的方法,從而降低對(duì)象之間的耦合度,增強(qiáng)系統(tǒng)的可維護(hù)性和可復(fù)用性。
在 Java 中,中介者模式可以使用以下步驟實(shí)現(xiàn):
定義一個(gè)中介者類(Mediator),該類包含了與各個(gè)同事類(Colleague)交互的邏輯。
public class Mediator {
public void performAction(Colleague colleague) {
// 處理同事類之間的交互邏輯
}
}
定義一個(gè)同事類(Colleague),該類與中介者類交互,并將自身的狀態(tài)傳遞給中介者。
public class Colleague {
private Mediator mediator;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
public void changeState() {
// 修改自身的狀態(tài)
mediator.performAction(this); // 調(diào)用中介者的方法,處理與其它同事類的交互邏輯
}
}
在客戶端代碼中,創(chuàng)建中介者和同事類的實(shí)例,并調(diào)用相應(yīng)的方法。
public class Client {
public static void main(String[] args) {
Mediator mediator = new Mediator();
Colleague colleague1 = new Colleague(mediator);
Colleague colleague2 = new Colleague(mediator);
// 設(shè)置同事1的狀態(tài),觸發(fā)中介者處理邏輯
colleague1.changeState();
// 設(shè)置同事2的狀態(tài),同樣會(huì)觸發(fā)中介者處理邏輯
colleague2.changeState();
}
}
在上述代碼中,中介者類 Mediator 集中處理同事類之間的交互邏輯,避免了同事類之間的直接交互,降低了系統(tǒng)的耦合度。同時(shí),通過將交互邏輯集中管理,也方便了對(duì)系統(tǒng)行為的擴(kuò)展和維護(hù)。
1.3.10、解釋器模式:定義一個(gè)解釋器接口,通過解釋器來解釋并執(zhí)行特定的語法規(guī)則。
解釋器模式提供了一種構(gòu)建解析、解釋和處理語言表達(dá)式的方式。在 Java 中,解釋器模式可以使用以下步驟實(shí)現(xiàn):
定義一個(gè)抽象表達(dá)式類(Expression),該類聲明了解釋表達(dá)式的方法。
public interface Expression {
int interpret(Context context);
}
定義一個(gè)具體表達(dá)式類(ConcreteExpression),該類實(shí)現(xiàn)了抽象表達(dá)式類中的 interpret() 方法。
public class ConcreteExpression implements Expression {
@Override
public int interpret(Context context) {
// 實(shí)現(xiàn)解釋表達(dá)式的邏輯
}
}
定義一個(gè)上下文類(Context),該類包含了與表達(dá)式相關(guān)的數(shù)據(jù)和操作。
public class Context {
private int value;
public Context(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
創(chuàng)建一個(gè)解釋器類(Interpreter),該類包含了與表達(dá)式相關(guān)的解釋邏輯。
public class Interpreter {
public int interpret(Expression expression) {
return expression.interpret(new Context(0)); // 傳入默認(rèn)的上下文對(duì)象
}
}
在客戶端代碼中,創(chuàng)建具體表達(dá)式和上下文對(duì)象,并調(diào)用解釋器類的 interpret() 方法來解釋表達(dá)式。文章來源:http://www.zghlxwxcb.cn/news/detail-684256.html
public class Client {
public static void main(String[] args) {
Expression expression = new ConcreteExpression(); // 創(chuàng)建具體表達(dá)式對(duì)象
Context context = new Context(10); // 創(chuàng)建上下文對(duì)象
Interpreter interpreter = new Interpreter(); // 創(chuàng)建解釋器對(duì)象
int result = interpreter.interpret(expression); // 調(diào)用解釋器解釋表達(dá)式,并獲取結(jié)果
System.out.println(result); // 輸出結(jié)果
}
}
在上述代碼中,解釋器模式通過定義抽象表達(dá)式類和具體表達(dá)式類,使得不同類型的表達(dá)式可以靈活地添加到系統(tǒng)中。同時(shí),通過將解釋邏輯封裝在解釋器類中,使得系統(tǒng)的可維護(hù)性和可復(fù)用性得到了提高。文章來源地址http://www.zghlxwxcb.cn/news/detail-684256.html
到了這里,關(guān)于【設(shè)計(jì)模式】Java設(shè)計(jì)模式詳細(xì)講解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!