国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

設(shè)計(jì)模式之【策略模式】,去掉繁瑣的if-else,實(shí)現(xiàn)算法的動(dòng)態(tài)替換

這篇具有很好參考價(jià)值的文章主要介紹了設(shè)計(jì)模式之【策略模式】,去掉繁瑣的if-else,實(shí)現(xiàn)算法的動(dòng)態(tài)替換。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。


全網(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、策略模式的三大角色

策略模式消除ifelse,設(shè)計(jì)模式與開(kāi)發(fā)規(guī)范,策略模式,設(shè)計(jì)模式,算法
策略模式的主要角色如下:

  • 抽象策略(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)展示給客戶。類圖如下:
策略模式消除ifelse,設(shè)計(jì)模式與開(kāi)發(fā)規(guī)范,策略模式,設(shè)計(jì)模式,算法

// 定義百貨公司所有促銷活動(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ì)。

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有很多子類:
策略模式消除ifelse,設(shè)計(jì)模式與開(kāi)發(fā)規(guī)范,策略模式,設(shè)計(jì)模式,算法文章來(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)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 設(shè)計(jì)模式:干掉if else的幾種方法

    存在的問(wèn)題: 如果業(yè)務(wù)邏輯過(guò)多 if else 可能要寫(xiě)多達(dá)幾百行,這樣代碼可讀性很差,不利于尋找bug和理解代碼 如果if后面的判斷邏輯過(guò)長(zhǎng),則代碼可讀性不強(qiáng) 如果將其寫(xiě)在一個(gè)核心代碼里面,則新增功能時(shí)需要修改核心代碼,要是不小心改到其他的代碼就涼涼了 當(dāng)業(yè)務(wù)邏輯

    2024年02月07日
    瀏覽(20)
  • 【狀態(tài)模式】拯救if-else堆出來(lái)的屎山代碼

    【狀態(tài)模式】拯救if-else堆出來(lái)的屎山代碼

    我想大家平時(shí)都在開(kāi)發(fā)重都遇見(jiàn)過(guò)屎山代碼,這些屎山代碼一般都是由于復(fù)雜且龐大的if-else造成的,狀態(tài)模式,是一種很好的優(yōu)化屎山代碼的設(shè)計(jì)模式,本文將采用兩個(gè)業(yè)務(wù)場(chǎng)景的示例來(lái)講解如何使用狀態(tài)模式拯救屎山代碼。 目錄 前言 1.網(wǎng)購(gòu)業(yè)務(wù)場(chǎng)景 1.1.需求 1.2.if else的實(shí)

    2024年02月12日
    瀏覽(17)
  • 設(shè)計(jì)模式第八講:常見(jiàn)重構(gòu)技巧 - 去除多余的if else

    設(shè)計(jì)模式第八講:常見(jiàn)重構(gòu)技巧 - 去除多余的if else

    最為常見(jiàn)的是代碼中使用很多的if/else,或者switch/case;如何重構(gòu)呢?方法特別多,本文是設(shè)計(jì)模式第八講,帶你學(xué)習(xí)其中的技巧。 通常業(yè)務(wù)代碼會(huì)包含這樣的邏輯:每種條件下會(huì)有不同的處理邏輯。比如兩個(gè)數(shù)a和b之間可以通過(guò)不同的操作符(+,-,*,/)進(jìn)行計(jì)算,初學(xué)者通

    2024年02月10日
    瀏覽(18)
  • Python if-else 速記

    編程中經(jīng)常使用速記符號(hào)來(lái)簡(jiǎn)化我們的工作。 速記符號(hào)是一種可以更簡(jiǎn)潔、更省時(shí)省力地完成工作的方法。 本文將討論 Python 中使用的速記符號(hào)作為 if-else 語(yǔ)句的快捷方式。 如前所述,速記符號(hào)是一種可以簡(jiǎn)潔地編寫(xiě)程序的方法。 到目前為止,我們?cè)?Python 中使用了許多速

    2024年02月11日
    瀏覽(22)
  • Python用if-else實(shí)現(xiàn)【猜數(shù)字】

    Python用if-else實(shí)現(xiàn)【猜數(shù)字】

    設(shè)置一個(gè) 范圍1-100的隨機(jī)整數(shù)變量 ,通過(guò) while 循環(huán),配合 input 語(yǔ)句,判斷輸入的數(shù)字是否等于隨機(jī)數(shù) 無(wú)限次機(jī)會(huì),直到猜中為止 每一次猜不中,會(huì)提示大了或小了 猜完數(shù)字后,提示猜了幾次 提示: 無(wú)限次機(jī)會(huì),終止條件不適合用數(shù)字累加來(lái)判斷 可以考慮布爾類型本身 (

    2024年02月12日
    瀏覽(18)
  • 策略模式+Spring配置類優(yōu)化多if..else思路

    策略模式+Spring配置類優(yōu)化多if..else思路

    場(chǎng)景: 假設(shè)設(shè)備上報(bào)不同類型的消息,我們要對(duì)不同類型的消息做不同的處理。如果我們通過(guò)if..else的方式處理的話會(huì)顯得比較冗余。 例如: 那么對(duì)于不同消息的不同的處理邏輯我們可以單獨(dú)放在一個(gè)實(shí)現(xiàn)類中,這些類有著相同的行為,所以我們可以定義一個(gè)接口: 針對(duì)于不

    2024年02月15日
    瀏覽(18)
  • mybatis使用xml中的if-else/choose

    最近需要使用 xml 文件來(lái)實(shí)現(xiàn)一些增刪改查,此文對(duì) 其中的 if-else 加以說(shuō)明 背景: 有一個(gè)引用類,假設(shè)叫 Student 現(xiàn)在我們查詢條件也被封裝成一個(gè)引用類,例如: 那么使用 xml 怎么來(lái)使用和接收呢? 首先肯定是在 mapper 里面有一個(gè)方法 然后在 xml 文件中寫(xiě)這個(gè)方法的具體實(shí)

    2024年04月23日
    瀏覽(20)
  • 不需要策略模式也能避免滿屏if/else

    不需要策略模式也能避免滿屏if/else

    java 復(fù)制代碼 public static void main(String[] args) { int a = 1; if(a == 1){ System.out.println(\\\"執(zhí)行a=1的邏輯\\\"); }else if (a == 2){ System.out.println(\\\"執(zhí)行a=2的邏輯\\\"); }else if (a == 3){ System.out.println(\\\"執(zhí)行a=3的邏輯\\\"); }else if (a == 4){ System.out.println(\\\"執(zhí)行a=4的邏輯\\\"); }else if (a == 5){ System.out.println(\\\"執(zhí)行a=5的邏輯

    2024年02月06日
    瀏覽(23)
  • 條件運(yùn)算符? : 與if-else語(yǔ)句的對(duì)比及用法詳解

    條件運(yùn)算符? : :給程序員提供了一種簡(jiǎn)便的方式進(jìn)行條件判斷和表達(dá)式的求值。在C語(yǔ)言中,條件運(yùn)算符? : 是一個(gè)三元運(yùn)算符,可以根據(jù)條件的真假來(lái)判斷輸出結(jié)果。本篇文章將詳細(xì)介紹條件運(yùn)算符的用法,以及與if-else語(yǔ)句的對(duì)比,并結(jié)合實(shí)例來(lái)進(jìn)一步理解。 條件運(yùn)算符?

    2024年02月05日
    瀏覽(45)
  • Verilog 不完整if-else和case產(chǎn)生鎖存latch

    Verilog 不完整if-else和case產(chǎn)生鎖存latch

    寫(xiě)這篇文章是因?yàn)楸拘“自谒㈩}過(guò)程中看到答主的代碼總是不把if-else寫(xiě)全,而我又記得不寫(xiě)全是可能產(chǎn)生latch的,對(duì)此很迷惑,仔細(xì)看過(guò)之后發(fā)現(xiàn)只有組合邏輯(電平觸發(fā))電路中的不完整if-else和case才會(huì)產(chǎn)生鎖存器latch。簡(jiǎn)單記錄一下。 參考文章: 1、https://blog.csdn.net/ainu

    2024年02月13日
    瀏覽(27)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包