【设计模式】策略模式与代理模式区别小结

                                                                           返回主页

最近学习设计模式,看到策略模式与代理模式,觉得两者之间很相似,于是写下这篇博文区别一下两者,便于以后查看。

策略模式

又称为政策模式。定义为“定义一组算法,将每个算法都封装起来,并且使它们之间可以互换”

策略模式代码解释

接口Strategy.java

/**
 * 抽象策略角色
 * @author Administrator
 * @date 2015年12月16日
 * @name Strategy.java
 */
public interface Strategy {
    //策略模式的运算法则
    public void doSomething();
}

定义一个或多个方法,在具体类中实现具体逻辑

具体决策类ConcreteStrategy1.java

/**
 * 具体决策角色
 * @author Administrator
 * @date 2015年12月16日
 * @name ConcreteStrategy1.java
 */
public class ConcreteStrategy1 implements Strategy {

    @Override
    public void doSomething() {
        System.out.println("具体策略1运算法则");
    }

}

实现Strategy接口

具体决策类ConcreteStrategy2.java

/**
 * 具体策略角色
 * @author Administrator
 * @date 2015年12月16日
 * @name ConcreteStrategy2.java
 */
public class ConcreteStrategy2 implements Strategy {

    @Override
    public void doSomething() {
        System.out.println("具体策略2运算法则");
    }

}

实现Strategy接口

封装角色Context.java

/**
 * 封装角色
 * @author Administrator
 * @date 2015年12月16日
 * @name Context.java
 */
public class Context {
    //抽象策略
    private Strategy strategy = null;
    //构造函数设置具体策略
    public Context(Strategy _strategy) {
        this.strategy = _strategy;
    }
    //封装后的策略方法
    public void doAnything() {
        this.strategy.doSomething();
    }

}

Context.java也叫上下文角色,屏蔽高层模块对策略的直接访问,符合开闭原则,减少因为增加模块而对整体的修改。要啥策略就从构造方法中传。

客户端代码Client.java

/**
 * 高层模块,测试类。用于调用
 * 
 * @author Administrator
 * @date 2015年12月16日
 * @name Client.java
 */
public class Client {

    public static void main(String[] args) {
        // 声明一个具体的策略
        Strategy strategy1 = new ConcreteStrategy1();
        // 声明上下文对象
        Context context1 = new Context(strategy1);
        // 执行封装之后的方法
        context1.doAnything();

        // 声明一个具体的策略
        Strategy strategy2 = new ConcreteStrategy1();
        // 声明上下文对象
        Context context2 = new Context(strategy2);
        // 执行封装之后的方法
        context2.doAnything();

    }
}

运行结果

具体策略1运算法则
具体策略1运算法则

代理模式

定义

为其他对象提供一种代理以控制对整个对象的访问

代理模式代码解释

接口IGamePlayer.java

package Version1;

public interface IGamePlayer {
    //登录
    public void login(String user, String passward);
    //杀怪
    public void killBoss();
    //升级
    public void upgrade();
}

该接口定义若干方法供实现

实现类GamePlayer.java

package Version1.Classes;

import Version1.IGamePlayer;

public class GamePlayer implements IGamePlayer {

    private String name = "";

    public GamePlayer(String _name) {
        this.name = _name;
    }

    @Override
    public void login(String user, String passward) {
        System.out.println("登录名为" + this.name + "用户登录成功");
    }

    @Override
    public void killBoss() {
        System.out.println(this.name + "过关斩将杀怪");
    }

    @Override
    public void upgrade() {
        System.out.println(this.name + "又升一级!O(∩_∩)O~");
    }

}

实现接口IGamePlayer,没什么好说的

实现类GamePlayerProxy.java(代理方法)

package Version2;

import Version1.IGamePlayer;

public class GamePlayerProxy implements IGamePlayer {

    private IGamePlayer gamePlayer;

    public GamePlayerProxy(IGamePlayer _gamePlayer) {
        this.gamePlayer = _gamePlayer;
    }

    @Override
    public void login(String user, String passward) {
        this.gamePlayer.login(user, passward);
    }

    @Override
    public void killBoss() {
        this.gamePlayer.killBoss();
    }

    @Override
    public void upgrade() {
        this.gamePlayer.upgrade();
    }

}

代理方法GamePlayerProxy实现IGamePlayer,构造方法传入参数IGamePlayer,即实际执行者。即实际执行者通过代理者进行动作。

客户端Client.java(测试类)

package Version2;

import Version1.IGamePlayer;
import Version1.Classes.GamePlayer;

public class Client {

    public static void main(String[] args) {
        IGamePlayer player = new GamePlayer("张三");
        IGamePlayer proxy = new GamePlayerProxy(player);
        System.out.println("开始时间" + "2015-12-03 10:42");
        proxy.login("", "password");
        proxy.killBoss();
        proxy.upgrade();
        System.out.println("结束时间" + "2015-12-03 12:42");

    }
}

运行结果

开始时间2015-12-03 10:42
登录名为张三用户登录成功
张三过关斩将杀怪
张三又升一级!O(∩_∩)O~
结束时间2015-12-03 12:42

代理模式使用场景很多,Spring的AOP(面向切面)就是一个典型的动态代理

两者的联系和区别

策略模式的重点在于封装角色,借用了代理模式的思路。

差别在于策略模式的封装角色和被封装的策略类不是使用同一个接口,
而代理模式的代理者和执行者实现了同一个接口,通过代理者间接执行执行者方法。

参考资料:《设计模式之禅》 秦小波