Java 设计模式 -- 命令模式

pbyp4943 8年前
   <h3><strong>前提</strong></h3>    <p>介绍这么模式之前,我们首先来看看它的类图。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/19c2b1b7930dde490962227c471b22ca.jpg"></p>    <p>根据这个图我们来分析一下何为命令模式。首先就是我们的 Client 想要实现一个功能,于是它就创建了一个 Command , 为了方便调用将 Command 封装在了 Invoker 中,当我们想调用的时候, Invoker 会执行内部 Command 提供的方法, Receiver 接收到 Command 的请求,为其提供底部支持。</p>    <p>多说无益,我将通过一个例子介绍命令模式。</p>    <h3><strong>实例</strong></h3>    <p>目前大部分的软件都支持用户自定义界面,比如说我们可以修改字体大小,背景颜色等。我们就以此为例。首先,写出两个类。</p>    <pre>  <code class="language-java">public class Font {      private String fontSize = "normal";        public String getFontSize() {          return fontSize;      }        public void setFontSize(String fontSize) {          this.fontSize = fontSize;      }  }  public class Background {      private String bgColor = "white";        public String getBgColor() {          return bgColor;      }        public void setBgColor(String bgColor) {          this.bgColor = bgColor;      }  }</code></pre>    <p>以上这两个类在命令模式的类图中扮演的是 Receiver 角色,提供底层支持。</p>    <pre>  <code class="language-java">public interface Command {      public void execute();  }</code></pre>    <p>这是 Command , 修改字体大小和背景的类都继承于此。</p>    <pre>  <code class="language-java">public class NormalFontCommand implements Command {      private Font font;        public NormalFontCommand(Font font) {          this.font = font;      }        @Override      public void execute() {          font.setFontSize("Normal");      }  }  public class LargeFontCommand implements Command {        private Font font;        public LargeFontCommand(Font font) {          this.font = font;      }        @Override      public void execute() {          font.setFontSize("Large");      }  }</code></pre>    <p>很简单的,我们只是在类中获得一个 Font 类的引用,然后调用 setFontSize() 方法对字体的大小进行设置。</p>    <p>因为背景颜色的种类特别多,如果我们针对每种颜色都编写一个类,那就太不实际了。所以我们决定用两个类去实现它,一个类表示是默认颜色,一个是类表示非默认颜色。</p>    <pre>  <code class="language-java">public class DefaultBackground implements Command {        private Background background;        public DefaultBackground(Background background) {          this.background = background;      }        @Override      public void execute() {          background.setBgColor("Default color");      }  }    public class CustomBackground implements Command {      private Background background;      private String color = null;        public CustomBackground(Background background) {          this.background = background;      }        @Override      public void execute() {          background.setBgColor("Custom background");      }  }</code></pre>    <p>好了,通过以上操作,我们不仅定义好了 Command ,还定义了 Receiver 类,下面就差 Invoker 类了。</p>    <pre>  <code class="language-java">public class Invoker {        private ArrayList<Command> commands;        public Invoker() {          commands = new ArrayList<>();      }        public void setCommand(int i, Command command) {          commands.add(i, command);      }        public void update(int i) {          commands.get(i).execute();      }  }</code></pre>    <p>用 ArrayList 存储 Command 命令,不过我们需要指定序号,方便以后我们使用。</p>    <p>下面开始进行测试</p>    <pre>  <code class="language-java">public class Client {        public static void main(String[] args) {            Font font = new Font();          Background background = new Background();            NormalFontCommand normalFontCommand = new NormalFontCommand(font);          LargeFontCommand largeFontCommand = new LargeFontCommand(font);          DefaultBackground defaultBackground = new DefaultBackground(background);          CustomBackground customBackground = new CustomBackground(background);            Invoker invoker = new Invoker();          invoker.setCommand(0, normalFontCommand);          invoker.setCommand(1, largeFontCommand);          invoker.setCommand(2, defaultBackground);          invoker.setCommand(3, customBackground);            invoker.update(3);            System.out.println(background.getBgColor());      }  }</code></pre>    <p>我们首先把所有的命令添加到了 Invoker , 然后直接调用 update() 方法就可以了。</p>    <p>这么做有什么好处呢?看的出来,可以将很多命令放进 Invoker , 它并不知道功能是如何实现的,它就像一个中介, Client 请求一个功能,它就将这个请求转给 Command 去实现。这种模式有很多的用途,比如说多功能遥控器,日志打印等。</p>    <p>还有一点不得不说的,我们可以使用宏命令,什么是宏命令呢?就是写一个 Command ,这个 Command 可以实现多个功能。比如说我们可以同时修改背景和</p>    <p>来自:http://www.jianshu.com/p/3fd3166c7662</p>    <p> </p>