柚子快報邀請碼778899分享:bash 設計模式——策略模式
柚子快報邀請碼778899分享:bash 設計模式——策略模式
策略模式
1. 引言2. 什么是策略模式?3. 策略模式的結構4. 策略模式的實現(xiàn)5. 策略模式的優(yōu)點6. 策略模式的缺點7. 策略模式的應用場景8. 策略模式與其他模式的關系9. Java標準庫中的策略模式1. java.util.Comparator示例:2. java.util.concurrent.ThreadPoolExecutor示例:3. javax.servlet.http.HttpServlet示例:4. java.io.InputStream示例:5. javax.swing.LayoutManager示例:
10. 總結
1. 引言
在軟件開發(fā)中,我們經(jīng)常需要實現(xiàn)一些算法或策略,而這些算法可能會隨著需求的變化而改變。策略模式就是為了應對這種情況而生的,它提供了一種靈活且可擴展的方式來管理和切換不同的算法。
2. 什么是策略模式?
策略模式(Strategy Pattern)是一種行為型設計模式,它定義了算法家族,分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變化獨立于使用算法的客戶端。
3. 策略模式的結構
策略模式主要包含以下三個角色:
Context(上下文): 持有一個Strategy的引用Strategy(抽象策略類): 定義了一個公共接口,各種不同的算法以不同的方式實現(xiàn)這個接口ConcreteStrategy(具體策略類): 實現(xiàn)了Strategy接口的具體算法
4. 策略模式的實現(xiàn)
一個電商系統(tǒng),需要根據(jù)不同的會員等級提供不同的折扣策略。
首先,定義一個折扣策略接口:
public interface DiscountStrategy {
double applyDiscount(double price);
}
然后,實現(xiàn)幾個具體的折扣策略:
// 普通會員折扣
public class RegularDiscountStrategy implements DiscountStrategy {
@Override
public double applyDiscount(double price) {
return price * 0.95; // 5%折扣
}
}
// 黃金會員折扣
public class GoldDiscountStrategy implements DiscountStrategy {
@Override
public double applyDiscount(double price) {
return price * 0.9; // 10%折扣
}
}
// 白金會員折扣
public class PlatinumDiscountStrategy implements DiscountStrategy {
@Override
public double applyDiscount(double price) {
return price * 0.85; // 15%折扣
}
}
接下來,創(chuàng)建一個上下文類來使用這些策略:
public class ShoppingCart {
private DiscountStrategy discountStrategy;
public void setDiscountStrategy(DiscountStrategy discountStrategy) {
this.discountStrategy = discountStrategy;
}
public double checkout(double price) {
if (discountStrategy == null) {
return price;
}
return discountStrategy.applyDiscount(price);
}
}
最后,可以在客戶端代碼中使用這個購物車ShoppingCart :
public class Client {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
// 普通會員購物
cart.setDiscountStrategy(new RegularDiscountStrategy());
System.out.println("Regular member's price: " + cart.checkout(100));
// 黃金會員購物
cart.setDiscountStrategy(new GoldDiscountStrategy());
System.out.println("Gold member's price: " + cart.checkout(100));
// 白金會員購物
cart.setDiscountStrategy(new PlatinumDiscountStrategy());
System.out.println("Platinum member's price: " + cart.checkout(100));
}
}
5. 策略模式的優(yōu)點
算法可以自由切換: 只要實現(xiàn)了策略接口,就可以自由地在不同策略間切換。避免使用多重條件判斷: 如果不使用策略模式,可能需要使用多重條件語句來選擇不同的算法。擴展性良好: 在不修改原有系統(tǒng)的基礎上,可以靈活地增加新的算法。策略類之間可以自由替換: 由于所有策略類都實現(xiàn)同一個接口,所以它們之間可以自由替換。
6. 策略模式的缺點
客戶端必須知道所有的策略類,并自行決定使用哪一個策略類。策略模式將造成產(chǎn)生很多策略類,可能會增加系統(tǒng)的復雜度。每一個策略都是一個單獨的類,復用性較低。
7. 策略模式的應用場景
當一個系統(tǒng)需要動態(tài)地在幾種算法中選擇一種時。當一個對象有很多的行為,如果不用模式,這些行為就只好使用多重條件選擇語句來實現(xiàn)。不希望客戶端知道復雜的、與算法相關的數(shù)據(jù)結構,在具體策略類中封裝算法和相關的數(shù)據(jù)結構,提高算法的保密性與安全性。
8. 策略模式與其他模式的關系
工廠模式: 工廠模式可以用來創(chuàng)建策略對象,與策略模式配合使用。狀態(tài)模式: 策略模式和狀態(tài)模式的結構幾乎完全一樣,但它們的意圖不同。命令模式: 命令模式可以使用策略模式來參數(shù)化命令對象。
9. Java標準庫中的策略模式
Java標準庫中有很多使用策略模式的例子。
1. java.util.Comparator
Comparator接口是Java中最常見的策略模式實現(xiàn)之一。它允許我們定義對象的自定義排序策略。
示例:
import java.util.*;
public class ComparatorExample {
public static void main(String[] args) {
List
// 使用自然順序(字母順序)
Collections.sort(names);
System.out.println("Natural order: " + names);
// 使用自定義比較器(按長度排序)
Collections.sort(names, new Comparator
@Override
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
});
System.out.println("Sorted by length: " + names);
// 使用Lambda表達式(按長度降序排序)
Collections.sort(names, (s1, s2) -> s2.length() - s1.length());
System.out.println("Sorted by length (descending): " + names);
}
}
在這個例子中,Comparator就是策略接口,不同的排序方法是具體的策略實現(xiàn)。
2. java.util.concurrent.ThreadPoolExecutor
ThreadPoolExecutor類使用策略模式來決定如何處理新提交的任務,特別是當線程池已滿時。
示例:
import java.util.concurrent.*;
public class ThreadPoolExample {
public static void main(String[] args) {
// 使用CallerRunsPolicy
ThreadPoolExecutor executorWithCallerRuns = new ThreadPoolExecutor(
2, 2, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue
new ThreadPoolExecutor.CallerRunsPolicy());
// 使用DiscardPolicy
ThreadPoolExecutor executorWithDiscard = new ThreadPoolExecutor(
2, 2, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue
new ThreadPoolExecutor.DiscardPolicy());
// 提交任務
for (int i = 0; i < 10; i++) {
final int taskId = i;
executorWithCallerRuns.execute(() -> {
System.out.println("Task " + taskId + " executed by " +
Thread.currentThread().getName());
});
}
executorWithCallerRuns.shutdown();
executorWithDiscard.shutdown();
}
}
這里,RejectedExecutionHandler接口是策略接口,CallerRunsPolicy和DiscardPolicy是具體的策略實現(xiàn)。
3. javax.servlet.http.HttpServlet
雖然不是嚴格意義上的策略模式,HttpServlet類使用了類似策略模式的方法來處理不同類型的HTTP請求。
示例:
import javax.servlet.http.*;
import java.io.IOException;
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
response.getWriter().println("GET request handled");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
response.getWriter().println("POST request handled");
}
// 其他HTTP方法...
}
在這個例子中,不同的HTTP方法(GET、POST等)可以看作是不同的策略。
4. java.io.InputStream
InputStream類及其子類使用了策略模式來實現(xiàn)不同的讀取策略。
示例:
import java.io.*;
public class InputStreamExample {
public static void main(String[] args) throws IOException {
// 文件輸入流策略
try (InputStream fileIn = new FileInputStream("example.txt")) {
int data = fileIn.read();
while(data != -1) {
System.out.print((char) data);
data = fileIn.read();
}
}
// 字節(jié)數(shù)組輸入流策略
byte[] bytes = "Hello, World!".getBytes();
try (InputStream byteArrayIn = new ByteArrayInputStream(bytes)) {
int data = byteArrayIn.read();
while(data != -1) {
System.out.print((char) data);
data = byteArrayIn.read();
}
}
}
}
這里,InputStream是抽象策略,F(xiàn)ileInputStream和ByteArrayInputStream是具體策略。
5. javax.swing.LayoutManager
Swing庫中的LayoutManager接口使用策略模式來定義不同的布局策略。
示例:
import javax.swing.*;
import java.awt.*;
public class LayoutExample {
public static void main(String[] args) {
JFrame frame = new JFrame("Layout Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 使用FlowLayout策略
JPanel flowPanel = new JPanel(new FlowLayout());
flowPanel.add(new JButton("Button 1"));
flowPanel.add(new JButton("Button 2"));
// 使用BorderLayout策略
JPanel borderPanel = new JPanel(new BorderLayout());
borderPanel.add(new JButton("North"), BorderLayout.NORTH);
borderPanel.add(new JButton("South"), BorderLayout.SOUTH);
frame.add(flowPanel, BorderLayout.NORTH);
frame.add(borderPanel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}
在這個例子中,LayoutManager是策略接口,F(xiàn)lowLayout和BorderLayout是具體的布局策略。
10. 總結
策略模式是一種非常實用的設計模式,它提供了管理算法族、分離算法實現(xiàn)和算法使用的有效方法。通過策略模式,可以在不修改原有系統(tǒng)的情況下,靈活地增加新的算法或行為。在實際開發(fā)中,應該根據(jù)具體情況來判斷是否使用策略模式,以達到代碼復用、增強擴展性和維護性的目的。
柚子快報邀請碼778899分享:bash 設計模式——策略模式
精彩鏈接
本文內容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉載請注明,如有侵權,聯(lián)系刪除。