全網(wǎng)最全最細(xì)的【設(shè)計(jì)模式】總目錄,收藏起來(lái)慢慢啃,看完不懂砍我
一、什么是策略模式
策略模式(Strategy Pattern)又叫政策模式(Policy Pattern),它是將定義的算法家族分別封裝起來(lái),讓它們之間可以互相替換,從而讓算法的變化不會(huì)影響到使用算法的用戶。屬于行為型模式。
策略模式使用的就是面向?qū)ο蟮睦^承和多態(tài)機(jī)制,從而實(shí)現(xiàn)同一行為在不同場(chǎng)景下具備不同實(shí)現(xiàn)。
1、策略模式應(yīng)用場(chǎng)景
策略模式在生活中應(yīng)用也非常多。比如一個(gè)人的交稅比率與他的工資有關(guān),不同工資對(duì)應(yīng)不同的稅率。再比如互聯(lián)網(wǎng)移動(dòng)支付,每次下單后付款都需要選擇支付方式。
策略模式可以解決在有多種算法相似的情況下,使用if-else或者switch-case所帶來(lái)的復(fù)雜性和臃腫性,策略模式通常適用于以下場(chǎng)景:
- 針對(duì)同一類型問(wèn)題,有多種處理方式,每一種都能獨(dú)立解決問(wèn)題;
- 一個(gè)類定義了多種行為,并且這些行為在這個(gè)類的操作中以多個(gè)條件語(yǔ)句的形式出現(xiàn),可將每個(gè)條件分支移入它們各自的策略類中以代替這些條件語(yǔ)句;
- 多個(gè)類只區(qū)別在表現(xiàn)行為不同,可以使用策略模式,在運(yùn)行時(shí)動(dòng)態(tài)選擇具體要執(zhí)行的行為;
- 算法需要自由切換的場(chǎng)景;
- 需要屏蔽算法規(guī)則的場(chǎng)景。
2、狀態(tài)模式與策略模式的區(qū)別
狀態(tài)模式和策略模式的UML類圖架構(gòu)幾乎完全一樣,但他們的應(yīng)用場(chǎng)景是不一樣的。策略模式多種算法行為擇其一都能滿足,彼此之間是獨(dú)立的,用戶可自行更換策略算法;而狀態(tài)模式各個(gè)狀態(tài)間是存在相互關(guān)系的,彼此之間在一定條件下存在自動(dòng)切換狀態(tài)效果,且用戶無(wú)法指定狀態(tài),只能設(shè)置初始狀態(tài)。
3、策略模式優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
- 策略類之間可以自由切換:由于策略類都實(shí)現(xiàn)同一個(gè)接口,所以使它們之間可以自由切換。
- 易于擴(kuò)展:增加一個(gè)新的策略只需要添加一個(gè)具體的策略類即可,基本不需要改變?cè)械拇a,符合“開(kāi)閉原則“
- 避免使用多重條件選擇語(yǔ)句(if else),充分體現(xiàn)面向?qū)ο笤O(shè)計(jì)思想。
缺點(diǎn):
- 客戶端必須知道所有的策略類,并自行決定使用哪一個(gè)策略類。
- 策略模式將造成產(chǎn)生很多策略類,可以通過(guò)使用享元模式在一定程度上減少對(duì)象的數(shù)量。
4、策略模式的三大角色
策略模式的主要角色如下:
- 抽象策略(Strategy)類:這是一個(gè)抽象角色,通常由一個(gè)接口或抽象類實(shí)現(xiàn)。此角色給出所有的具體策略類所需的接口。
- 具體策略(Concrete Strategy)類:實(shí)現(xiàn)了抽象策略定義的接口,提供具體的算法實(shí)現(xiàn)或行為。
- 環(huán)境(Context)類:用來(lái)操作策略的上下文環(huán)境,屏蔽高層模塊(客戶端)對(duì)策略、算法的直接訪問(wèn),封裝可能存在的變化。
注:策略模式中的上下文環(huán)境(Context),其職責(zé)本來(lái)是隔離客戶端與策略類的耦合,讓客戶端完全與上下文環(huán)境溝通,無(wú)需關(guān)心具體策略。
二、實(shí)例
1、策略模式的一般寫(xiě)法
//抽象策略類 Strategy
public interface IStrategy {
void algorithm();
}
//具體策略類 ConcreteStrategy
public class ConcreteStrategyA implements IStrategy {
public void algorithm() {
System.out.println("Strategy A");
}
}
//具體策略類 ConcreteStrategy
public class ConcreteStrategyB implements IStrategy {
public void algorithm() {
System.out.println("Strategy B");
}
}
//上下文環(huán)境
public class Context {
private IStrategy mStrategy;
public Context(IStrategy strategy) {
this.mStrategy = strategy;
}
public void algorithm() {
this.mStrategy.algorithm();
}
}
public class Test {
public static void main(String[] args) {
//選擇一個(gè)具體策略
IStrategy strategy = new ConcreteStrategyA();
//來(lái)一個(gè)上下文環(huán)境
Context context = new Context(strategy);
//客戶端直接讓上下文環(huán)境執(zhí)行算法
context.algorithm();
}
}
2、促銷活動(dòng)案例
一家百貨公司在定年度的促銷活動(dòng)。針對(duì)不同的節(jié)日(春節(jié)、中秋節(jié)、圣誕節(jié))推出不同的促銷活動(dòng),由促銷員將促銷活動(dòng)展示給客戶。類圖如下:
// 定義百貨公司所有促銷活動(dòng)的共同接口
public interface Strategy {
void show();
}
// 定義具體策略角色(Concrete Strategy):每個(gè)節(jié)日具體的促銷活動(dòng)
//為春節(jié)準(zhǔn)備的促銷活動(dòng)A
public class StrategyA implements Strategy {
public void show() {
System.out.println("買一送一");
}
}
//為中秋準(zhǔn)備的促銷活動(dòng)B
public class StrategyB implements Strategy {
public void show() {
System.out.println("滿200元減50元");
}
}
//為圣誕準(zhǔn)備的促銷活動(dòng)C
public class StrategyC implements Strategy {
public void show() {
System.out.println("滿1000元加一元換購(gòu)任意200元以下商品");
}
}
// 定義環(huán)境角色(Context):用于連接上下文,即把促銷活動(dòng)推銷給客戶,這里可以理解為銷售員
public class SalesMan {
//持有抽象策略角色的引用
private Strategy strategy;
public SalesMan(Strategy strategy) {
this.strategy = strategy;
}
//向客戶展示促銷活動(dòng)
public void salesManShow(){
strategy.show();
}
}
// 測(cè)試類
public class Client {
public static void main(String[] args) {
//春節(jié)來(lái)了,使用春節(jié)促銷活動(dòng)
SalesMan salesMan = new SalesMan(new StrategyA());
//展示促銷活動(dòng)
salesMan.salesManShow();
System.out.println("==============");
//中秋節(jié)到了,使用中秋節(jié)的促銷活動(dòng)
salesMan.setStrategy(new StrategyB());
//展示促銷活動(dòng)
salesMan.salesManShow();
System.out.println("==============");
//圣誕節(jié)到了,使用圣誕節(jié)的促銷活動(dòng)
salesMan.setStrategy(new StrategyC());
//展示促銷活動(dòng)
salesMan.salesManShow();
}
}
此時(shí),我們發(fā)現(xiàn),上面的測(cè)試代碼放到實(shí)際業(yè)務(wù)場(chǎng)景其實(shí)并不實(shí)用,因?yàn)槲覀冏龌顒?dòng)時(shí)往往是要根據(jù)不同的需求對(duì)促銷策略進(jìn)行動(dòng)態(tài)選擇的,并不會(huì)一次性執(zhí)行多種優(yōu)惠,所以我們代碼通常會(huì)這樣寫(xiě):
public class Client {
public static void main(String[] args) {
SalesMan salesMan = null;
String saleKey = "A";
if(saleKey.equals("A")){
//春節(jié)來(lái)了,使用春節(jié)促銷活動(dòng)
salesMan = new SalesMan(new StrategyA());
} else if (saleKey.equals("B")) {
//中秋節(jié)到了,使用中秋節(jié)的促銷活動(dòng)
salesMan = new SalesMan(new StrategyB());
} // ...
//展示促銷活動(dòng)
salesMan.salesManShow();
}
}
這樣改造之后,滿足了業(yè)務(wù)需求,客戶可以根據(jù)自己的需求選擇不同的優(yōu)惠策略了。但是這里的if-else隨著促銷活動(dòng)的增多會(huì)越來(lái)越復(fù)雜,我們可以使用單例模式和工廠模式進(jìn)行優(yōu)化:
public class SalesMan {
public static final String SaleKeyA = "A";
public static final String SaleKeyB = "B";
public static final String SaleKeyC = "C";
private static Map<String, Strategy> sales = new HashMap<String, Strategy>();
static {
sales.put(SaleKeyA, new StrategyA());
sales.put(SaleKeyB, new StrategyB());
sales.put(SaleKeyC, new StrategyC());
}
public Strategy getStrategy(String key) {
Strategy strategy = sales.get(key);
if(strategy == null){
throw new RuntimeException("策略有誤");
}
return strategy;
}
}
public class Client {
public static void main(String[] args) {
SalesMan salesMan = new SalesMan();
String saleKey = "A";
Strategy strategy = salesMan.getStrategy(saleKey);
//展示促銷活動(dòng)
strategy.show();
}
}
3、網(wǎng)購(gòu)訂單支付案例
我們?cè)诰W(wǎng)購(gòu)下單時(shí),會(huì)提示選擇支付方式,通常會(huì)有支付寶、微信、銀聯(lián)等等支付方式,如果沒(méi)選擇,系統(tǒng)也會(huì)使用默認(rèn)的支付方式,我們使用策略模式來(lái)模擬此場(chǎng)景:
// 支付狀態(tài)包裝類
public class MsgResult {
private int code;
private Object data;
private String msg;
public MsgResult(int code, String msg, Object data) {
this.code = code;
this.data = data;
this.msg = msg;
}
@Override
public String toString() {
return "MsgResult{" +
"code=" + code +
", data=" + data +
", msg='" + msg + '\'' +
'}';
}
}
// 定義支付邏輯,具體支付交由子類實(shí)現(xiàn)
public abstract class Payment {
public abstract String getName();
//通用邏輯放到抽象類里面實(shí)現(xiàn)
public MsgResult pay(String uid, double amount){
//余額是否足夠
if(queryBalance(uid) < amount){
return new MsgResult(500,"支付失敗","余額不足");
}
return new MsgResult(200,"支付成功","支付金額" + amount);
}
protected abstract double queryBalance(String uid);
}
// 定義具體支付方式
public class AliPay extends Payment {
public String getName() {
return "支付寶";
}
protected double queryBalance(String uid) {
return 900;
}
}
public class JDPay extends Payment {
public String getName() {
return "京東白條";
}
protected double queryBalance(String uid) {
return 500;
}
}
public class UnionPay extends Payment {
public String getName() {
return "銀聯(lián)支付";
}
protected double queryBalance(String uid) {
return 120;
}
}
public class WechatPay extends Payment {
public String getName() {
return "微信支付";
}
protected double queryBalance(String uid) {
return 263;
}
}
// 策略管理類
public class PayStrategy {
public static final String ALI_PAY = "AliPay";
public static final String JD_PAY = "JdPay";
public static final String WECHAT_PAY = "WechatPay";
public static final String UNION_PAY = "UnionPay";
public static final String DEFAULT_PAY = ALI_PAY;
private static Map<String,Payment> strategy = new HashMap<String,Payment>();
static {
strategy.put(ALI_PAY,new AliPay());
strategy.put(JD_PAY,new JDPay());
strategy.put(WECHAT_PAY,new WechatPay());
strategy.put(UNION_PAY,new UnionPay());
}
public static Payment get(String payKey){
if(!strategy.containsKey(payKey)){
return strategy.get(DEFAULT_PAY);
}
return strategy.get(payKey);
}
}
// 訂單類
public class Order {
private String uid;
private String orderId;
private double amount;
public Order(String uid, String orderId, double amount) {
this.uid = uid;
this.orderId = orderId;
this.amount = amount;
}
public MsgResult pay(){
return pay(PayStrategy.DEFAULT_PAY);
}
public MsgResult pay(String payKey){
Payment payment = PayStrategy.get(payKey);
System.out.println("歡迎使用" + payment.getName());
System.out.println("本次交易金額為" + amount + ",開(kāi)始扣款");
return payment.pay(uid,amount);
}
}
// 測(cè)試類
public class Test {
public static void main(String[] args) {
Order order = new Order("1","orderid",324.5);
System.out.println(order.pay(PayStrategy.UNION_PAY));
}
}
4、DispatcherServlet的優(yōu)化
我們都知道SpringMVC的請(qǐng)求都是通過(guò)DispatcherServlet的doDispatch方法進(jìn)行分發(fā)的,如果讓我們?cè)O(shè)計(jì),可能會(huì)這樣實(shí)現(xiàn):
public class DispatcherServlet extends HttpServlet {
private void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
String uri = request.getRequestURI();
String mid = request.getParameter("mid");
if("getMemberById".equals(uri)){
new MemberController().getMemberById(mid);
} else if("getOrder".equals(uri)) {
new OrderController().getOrder();
}// ...
}
}
上面的代碼擴(kuò)展性確實(shí)不太優(yōu)雅,我們可以使用策略模式進(jìn)行優(yōu)化:
public class DispatcherServlet extends HttpServlet {
private List<Handler> handlerMapping = new ArrayList<Handler>();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doDispatch(req,resp);
}
private void doDispatch(HttpServletRequest req, HttpServletResponse resp) {
String uri = req.getRequestURI();
// 使用uri匹配handler
Handler handler = null;
for (Handler h : handlerMapping) {
if(uri.equals(h.getUrl())){
handler = h;
break;
}
}
// 將具體任務(wù)分發(fā)給Method
Object result = null;
try {
result = handler.getMethod().invoke(handler.getController());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
// 寫(xiě)回結(jié)果
try {
resp.getWriter().write((String) result);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void init() throws ServletException {
try {
handlerMapping.add(new Handler().setController(MemberController.class.newInstance())
.setMethod(MemberController.class.getMethod("getMemberById", new Class[]{String.class}))
.setUrl("/web/getMemberById.json"));
handlerMapping.add(new Handler().setController(OrderController.class.newInstance())
.setMethod(OrderController.class.getMethod("getOrderById", new Class[]{String.class}))
.setUrl("/web/getOrderById.json"));
// ...其他handler
}catch (Exception e){
e.printStackTrace();
}
}
}
class Handler {
private Object controller;
private Method method;
private String url;
public Object getController() {
return controller;
}
public Handler setController(Object controller) {
this.controller = controller;
return this;
}
public Method getMethod() {
return method;
}
public Handler setMethod(Method method) {
this.method = method;
return this;
}
public String getUrl() {
return url;
}
public Handler setUrl(String url) {
this.url = url;
return this;
}
}
5、文件排序案例
我們?cè)偈褂靡粋€(gè)文件排序的案例加深策略模式的印象。
有這樣一個(gè)需求,希望寫(xiě)一個(gè)小程序,實(shí)現(xiàn)對(duì)一個(gè)文件進(jìn)行排序的功能。不同大小的文件排序的算法是不同的,我們初步可能會(huì)這樣實(shí)現(xiàn):
public class Sorter {
private static final long GB = 1000 * 1000 * 1000;
public void sortFile(String filePath) {
// 省略校驗(yàn)邏輯
File file = new File(filePath);
long fileSize = file.length();
if (fileSize < 6 * GB) { // [0, 6GB)
quickSort(filePath);
} else if (fileSize < 10 * GB) { // [6GB, 10GB)
externalSort(filePath);
} else if (fileSize < 100 * GB) { // [10GB, 100GB)
concurrentExternalSort(filePath);
} else { // [100GB, ~)
mapreduceSort(filePath);
}
}
private void quickSort(String filePath) {
// 快速排序
}
private void externalSort(String filePath) {
// 外部排序
}
private void concurrentExternalSort(String filePath) {
// 多線程外部排序
}
private void mapreduceSort(String filePath) {
// 利用MapReduce多機(jī)排序
}
}
public class SortingTool {
public static void main(String[] args) {
Sorter sorter = new Sorter();
sorter.sortFile(args[0]);
}
}
以上代碼并不能體現(xiàn)面向?qū)ο蟮镊攘?,完全是面向過(guò)程的,而我們?nèi)粘i_(kāi)發(fā)中這樣的代碼也是占大多數(shù)。
我們使用策略模式進(jìn)行重構(gòu):
// 策略接口
public interface ISortAlg {
void sort(String filePath);
}
// 具體策略類
public class QuickSort implements ISortAlg {
@Override
public void sort(String filePath) {
//...
}
}
public class ExternalSort implements ISortAlg {
@Override
public void sort(String filePath) {
//...
}
}
public class ConcurrentExternalSort implements ISortAlg {
@Override
public void sort(String filePath) {
//...
}
}
public class MapReduceSort implements ISortAlg {
@Override
public void sort(String filePath) {
//...
}
}
// 排序
public class SortAlgFactory {
private static final Map<String, ISortAlg> algs = new HashMap<>();
static {
algs.put("QuickSort", new QuickSort());
algs.put("ExternalSort", new ExternalSort());
algs.put("ConcurrentExternalSort", new ConcurrentExternalSort());
algs.put("MapReduceSort", new MapReduceSort());
}
public static ISortAlg getSortAlg(String type) {
if (type == null || type.isEmpty()) {
throw new IllegalArgumentException("type should not be empty.");
}
return algs.get(type);
}
}
public class Sorter {
private static final long GB = 1000 * 1000 * 1000;
public void sortFile(String filePath) {
// 省略校驗(yàn)邏輯
File file = new File(filePath);
long fileSize = file.length();
ISortAlg sortAlg;
if (fileSize < 6 * GB) { // [0, 6GB)
sortAlg = SortAlgFactory.getSortAlg("QuickSort");
} else if (fileSize < 10 * GB) { // [6GB, 10GB)
sortAlg = SortAlgFactory.getSortAlg("ExternalSort");
} else if (fileSize < 100 * GB) { // [10GB, 100GB)
sortAlg = SortAlgFactory.getSortAlg("ConcurrentExternalSort");
} else { // [100GB, ~)
sortAlg = SortAlgFactory.getSortAlg("MapReduceSort");
}
sortAlg.sort(filePath);
}
}
Sorter 類中的 sortFile() 函數(shù)還是有一堆 if-else 邏輯。這里的 if-else 邏輯分支不多、也不復(fù)雜,這樣寫(xiě)完全沒(méi)問(wèn)題。但如果你特別想將 if-else 分支判斷移除掉,那也是有辦法的。我直接給出代碼,你一看就能明白。實(shí)際上,這也是基于查表法來(lái)解決的,其中的“algs”就是“表”。
public class Sorter {
private static final long GB = 1000 * 1000 * 1000;
private static final List<AlgRange> algs = new ArrayList<>();
static {
algs.add(new AlgRange(0, 6*GB, SortAlgFactory.getSortAlg("QuickSort")));
algs.add(new AlgRange(6*GB, 10*GB, SortAlgFactory.getSortAlg("ExternalSort")));
algs.add(new AlgRange(10*GB, 100*GB, SortAlgFactory.getSortAlg("ConcurrentExternalSort")));
algs.add(new AlgRange(100*GB, Long.MAX_VALUE, SortAlgFactory.getSortAlg("MapReduceSort")));
}
public void sortFile(String filePath) {
// 省略校驗(yàn)邏輯
File file = new File(filePath);
long fileSize = file.length();
ISortAlg sortAlg = null;
for (AlgRange algRange : algs) {
if (algRange.inRange(fileSize)) {
sortAlg = algRange.getAlg();
break;
}
}
sortAlg.sort(filePath);
}
private static class AlgRange {
private long start;
private long end;
private ISortAlg alg;
public AlgRange(long start, long end, ISortAlg alg) {
this.start = start;
this.end = end;
this.alg = alg;
}
public ISortAlg getAlg() {
return alg;
}
public boolean inRange(long size) {
return size >= start && size < end;
}
}
}
6、Spring中策略模式簡(jiǎn)單應(yīng)用
策略模式在實(shí)際開(kāi)發(fā)中的應(yīng)用
@Autowired
private Map<String,MyService> ServiceMap;
@Slf4j
@Service("MyServiceImpl")
public class MyServiceImpl implements MyService {}
Spring在自動(dòng)注入時(shí),使用Map的話,key就是接口實(shí)現(xiàn)類Bean的名稱,value就是對(duì)應(yīng)的Bean實(shí)例。
三、源碼中的策略模式
1、Comparator接口
JDK中一個(gè)常用的比較器Comparator接口,有一個(gè)常用的方法compare():
public interface Comparator<T> {
int compare(T o1, T o2);
}
Comparator抽象下面有非常多的實(shí)現(xiàn)類,我們經(jīng)常會(huì)把Comparator作為參數(shù)傳入作為排序策略,例如Arrays類的parallelSort方法等:
public class Arrays{
public static <T> void sort(T[] a, Comparator<? super T> c) {
if (c == null) {
sort(a);
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
}
Arrays就是一個(gè)環(huán)境角色類,這個(gè)sort方法可以傳一個(gè)新策略讓Arrays根據(jù)這個(gè)策略來(lái)進(jìn)行排序。就比如下面的測(cè)試類。
public class demo {
public static void main(String[] args) {
Integer[] data = {12, 2, 3, 2, 4, 5, 1};
// 實(shí)現(xiàn)降序排序
Arrays.sort(data, new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
System.out.println(Arrays.toString(data)); //[12, 5, 4, 3, 2, 2, 1]
}
}
這里我們?cè)谡{(diào)用Arrays的sort方法時(shí),第二個(gè)參數(shù)傳遞的是Comparator接口的子實(shí)現(xiàn)類對(duì)象。所以Comparator充當(dāng)?shù)氖浅橄蟛呗越巧?,而具體的子實(shí)現(xiàn)類充當(dāng)?shù)氖蔷唧w策略角色。環(huán)境角色類(Arrays)應(yīng)該持有抽象策略的引用來(lái)調(diào)用。那么,Arrays類的sort方法到底有沒(méi)有使用
Comparator子實(shí)現(xiàn)類中的 compare() 方法嗎?讓我們繼續(xù)查看TimSort類的 sort() 方法,代碼如下:
static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
T[] work, int workBase, int workLen) {
assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;
int nRemaining = hi - lo;
if (nRemaining < 2)
return; // Arrays of size 0 and 1 are always sorted
// If array is small, do a "mini-TimSort" with no merges
if (nRemaining < MIN_MERGE) {
int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
binarySort(a, lo, hi, lo + initRunLen, c);
return;
}
/**
* March over the array once, left to right, finding natural runs,
* extending short natural runs to minRun elements, and merging runs
* to maintain stack invariant.
*/
TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen);
int minRun = minRunLength(nRemaining);
do {
// Identify next run
int runLen = countRunAndMakeAscending(a, lo, hi, c);
// If run is short, extend to min(minRun, nRemaining)
if (runLen < minRun) {
int force = nRemaining <= minRun ? nRemaining : minRun;
binarySort(a, lo, lo + force, lo + runLen, c);
runLen = force;
}
// Push run onto pending-run stack, and maybe merge
ts.pushRun(lo, runLen);
ts.mergeCollapse();
// Advance to find next run
lo += runLen;
nRemaining -= runLen;
} while (nRemaining != 0);
// Merge all remaining runs to complete sort
assert lo == hi;
ts.mergeForceCollapse();
assert ts.stackSize == 1;
}
上面的代碼中最終會(huì)跑到 countRunAndMakeAscending() 這個(gè)方法中。我們可以看見(jiàn),只用了compare方法,所以在調(diào)用Arrays.sort方法只傳具體compare重寫(xiě)方法的類對(duì)象就行,這也是Comparator接口中必須要子類實(shí)現(xiàn)的一個(gè)方法。
2、Spring的InstantiationStrategy
Spring初始化用到的InstantiationStrategy接口:
public interface InstantiationStrategy {
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner)
throws BeansException;
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
Constructor<?> ctor, Object... args) throws BeansException;
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, Method factoryMethod, Object... args)
throws BeansException;
}
它有兩種策略:CglibSubclassingInstantiationStrategy和SimpleInstantiationStrategy,我們發(fā)現(xiàn)了CglibSubclassingInstantiationStrategy繼承了SimpleInstantiationStrategy,說(shuō)明在實(shí)際應(yīng)用中多種策略之間還可以繼承使用。我們可以作為一個(gè)參考,在實(shí)際業(yè)務(wù)場(chǎng)景中,可以根據(jù)需要進(jìn)行設(shè)計(jì)。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-707086.html
3、Spring的Resource
package org.springframework.core.io;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import org.springframework.lang.Nullable;
public interface Resource extends InputStreamSource {
boolean exists();
default boolean isReadable() {
return exists();
}
default boolean isOpen() {
return false;
}
default boolean isFile() {
return false;
}
URL getURL() throws IOException;
URI getURI() throws IOException;
File getFile() throws IOException;
default ReadableByteChannel readableChannel() throws IOException {
return Channels.newChannel(getInputStream());
}
long contentLength() throws IOException;
long lastModified() throws IOException;
Resource createRelative(String relativePath) throws IOException;
@Nullable
String getFilename();
String getDescription();
}
Resource有很多子類:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-707086.html
到了這里,關(guān)于設(shè)計(jì)模式之【策略模式】,去掉繁瑣的if-else,實(shí)現(xiàn)算法的動(dòng)態(tài)替換的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!