设计模式之策略模式(Strategy Pattern)

来源:互联网 发布:代码段和数据段 编辑:程序博客网 时间:2024/04/27 16:20

模式意图

完成一件事情, 可能有多种方法, 每种方式称为一种策略, 我们可以根据需要选择不同的方法.

模式结构

Context类: 需要具体的策略来执行任务.
AbstractStrategy类: 抽象的策略定义.
ConcreteStrategyX: 具体的某种策略.

策略模式类图

看起来策略模式十分清晰, 下面是示例代码:

Context

public class Context {    private AbstractStrategy strategy;    public void setStragety(AbstractStrategy strategy) {        this.strategy = strategy;    }    public void algorithm() {        this.strategy.algorithm();    }}

抽象策略类: AbstractStrategy

public abstract class AbstractStrategy {    public abstract void algorithm();}

具体策略A: ConcreteStrategyA

public class ConcreteStrategyA extends AbstractStrategy {    @Override    public void algorithm() {        System.err.println("ConcreteStrategyA");    }}

客户端调用过程

Context cxt = new Context();AbstractStrategy strategy = new ConcreteStrategyA();cxt.setStragety(strategy);cxt.algorithm();

显然, 策略模式提供了对”开闭原则”的完美支持, 但是客户端必须清楚知道具体策略类,
以便决定使用哪一个策略类. 而且在具体策略增多的时候, 会增加很多具体的策略类.

模式应用

Java SE中的布局管理器(LayoutManager)

import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JFrame;import javax.swing.JOptionPane;import javax.swing.JButton;public class GridLayoutDemo {    public static void main(String[] args) {        JFrame f = new JFrame("GridLayout Test");        f.setSize(300, 300);        // 这里设置布局        f.setLayout(new GridLayout(3, 3, 5, 5));        for (int i = 1; i < 10; i++) {            JButton btn = new JButton(String.valueOf(i));            btn.addActionListener(new ActionListener() {                @Override                public void actionPerformed(ActionEvent e) {                    JOptionPane.showMessageDialog(                            null,                             btn.getText(),                            "you clicked is: ",                            JOptionPane.INFORMATION_MESSAGE);                }            });            f.add(btn);        }        f.setVisible(true);        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    }}

运行效果:

GridLayout图片

java中的动态代理应用就有策略模式的体现:

public Shop createAppleShopProxy() {    return (Shop) Proxy.newProxyInstance(        AppleProxyShop.class.getClassLoader(),        appleShop.getClass().getInterfaces(),         // 代理功能的具体实现, 也就是具体策略        new InvocationHandler() {            @Override            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                String methodName = method.getName();                if (methodName.equals("sell")) {                    System.out.println("welcome to apple proxy shop");                    return method.invoke(appleShop, args);                }                return method.invoke(appleShop, args);            }        });}/********** 客户端通过"代理商店"购买手机 **********/AppleProxyShop proxy = new AppleProxyShop();Shop appleShop = proxy.createAppleShopProxy();System.out.println(appleShop.sell("iphone6", 599));System.out.println(appleShop.afterSale());// 输出如下:welcome to apple proxy shop // 代理拦截sell方法起作用了iphone6 is $599--AppleShopthanks for buying iPhone --AppleShopAppleShop afterSale --AppleShop // 未拦截, 直接调用真实对象的方法

js中数组的sort方法:

var arr = Array.from({length: 5})    .map((v, i) => i + 1);// [1, 2, 3, 4, 5]console.log(arr);// 随机排序arr.sort(() => .5 - Math.random());// [4, 2, 1, 5, 3], 顺序随机console.log(arr);

可以看出, sort方法可以根据需要传入指定的排序策略, 也是策略模式的应用.

欢迎补充指正!

阅读全文
0 0
原创粉丝点击