Java简单工厂模式和命令模式

以下内容部分来自 疯狂Java讲义/李刚 ,博客仅用于个人笔记及帮助他人用途,无任何商业目的,如有侵权,请联系作者删除。

1 简单工厂模式

1.1 简单工厂模式简介

有一个场景:假设程序中有个Computer 类需要组合一个输出设备,现在有两个选择:直接让 Computer 类组合一个 Printer ,或者让 Computer 类组合一个 Output, 那么到底采用哪种方式更好呢?
假设让Computer类组合一个 Printer对象,如果有一天系统需要重构,需要使用 BetterPrinter来代替 Printer,于是我们需要打开 Computer 类源代码进行修改。如果系统中只有一个 Computer 类组合了 Printer还好,但如果系统中有 100 个类组合了Printer,甚至 1000 个,10000个…将意味着我们要打开100个1000个类进行修改,这是多么大的工作量!
为了避免这个问题,我们让Computer类组合一个 Output类型的对象,将 Computer 类与 Printer 类完全分离。Computer对象实际组合的是 Printer 对象还是 BetterPrinter 对象,对 Computer完全透明。当 Printer 对象切换到 BetterPrinter对象时,系统完全不受影响。

1.2 代码实现

Computer.java:

package zhangke.SimpleFactoryMode;
import zhangke.SimpleFactoryMode.Output;
public class Computer{
  private Output out;
  public Computer(Output out){
    this.out = out;
  }
  public void keyIn(String msg){
    out.getData(msg);
  }
  public void print(){
    out.out();
  }
}

上面的Computer 类已经完全提供与 Printer 类分离,只是与 Output 接口耦合。Computer 不在负责创建 Output 对象,系统提供一个 Output 工厂来负责生成 Output 对象,这个 OutputFactory 工厂类代码如下:

OutputFactory.java:

package zhangke.SimpleFactoryMode;
public class OutputFactory{
  public Output getOutput(){
    return new BetterPrinter();
  }
  public static void main(String[] args){
    OutputFactory of = new OutputFactory();
    Computer c = new Computer(of.getOutput());
    c.keyIn("Test01");
    c.keyIn("Test02");
    c.print();
  }
}

如果系统需要将Printer 改为 BetterPrinter实现类,只需让BetterPrinter 实现 Output 接口,并改变 OutputFactory 类中的 getOut 方法即可。

BetterPrinter .java

package zhangke.SimpleFactoryMode;
public class BetterPrinter implements Output{
  private String[] printData=new String[MAX_CACHE_LINE];
  private int dataNum=0;
  public void out(){
    while(dataNum>0){
      System.out.println("高速打印机:"+printData[0]);
      System.arraycopy(printData,1,printData,0,--dataNum);
    }
  }
  public void getData(String msg){
    if(dataNum>=MAX_CACHE_LINE*2){
      System.out.println("输出队列已满,添加失败!");
    }else{
      printData[dataNum++]=msg;
    }
  }
}

上面的 BetterPrinter 类也实现了 Output 接口,因此也可当成 Output 对象使用。

Output.java

package zhangke.SimpleFactoryMode;
public interface Output{
//接口里定义的 FIeld 只能是常量
int MAX_CACHE_LINE = 50;
//接口里定义的只能是 public 的抽象实例方法
void out();
void getData(String mag);
}

通过这种方式,我们把所有生成的 Output 对象的逻辑集中在 OutputFactory 工厂类中管理,而所有需要使用 Output 对象的类只需与 Output 接口耦合,而不是与具体的实现类耦合。即使系统中很多类使用了 Printer 对象,只要 OutputFactory 类的 getOutput 方法生成的 Output对象是BetterPrinter 对象,则它们全部都会改为使用 BetterPrinter 对象,而所有程序无须修改,只需要修改 OutputFactory 工厂类的 getOutput方法实现即可。

上面介绍的就是一种被称为“简单工厂”的设计模式,所谓的设计模式,就是对经常出现的软件设计问题的成熟解决方案。很多人把设计模式想象成非常高深的概念,实际上设计模式仅仅是对特定问题的一种惯性思维。实际上设计模式的理解必须以足够的代码积累量作为基础,最好是经历过某种苦痛,或者正在经历一种苦痛,就会对设计模式有较深的感受。

2 命令模式

2.1 命令模式简介

考虑这样一个场景:某个方法需要完成一个任务,但这个行为的具体实现无法确定,必须等到执行该方法是才可以确定。具体一点:假设有个方法需要遍历某个数组元素,但无法确定在遍历数组元素时如何处理这些元素,需要在调用该方法时指定具体的处理行为。
这个要求看起来有点奇怪:这个方法不仅需要普通数据可以变化甚至还有方法执行体也需要变化,难道我们把“处理行为”作为一个参数传入该方法?
对于这样一个需求,我们必须把“处理行为”作为参数传入该方法,这个“处理行为”用编程来实现就是一段代码,那如何把这段代码传入该方法呢?
因为Java不允许代码块单独存在,因此我们使用一个 Command 接口来定义一个方法,用这个方法来封装“处理行为”。

2.2 代码实现

Command.java:

package zhangke.CommandMode;
public interface Command{
  public abstract void process(int[] target);
}

ProcessArray.java:

package zhangke.CommandMode;
public class ProcessArray{
  public void process(int[] target,Command cmd){
    cmd.process(target);
  }
}

通过一个Command 接口,就实现了让 ProcessArray.java 类和具体“处理行为”的分离,程序 使用Command接口代表了对数组的处理行为。Command 接口也没有提供真正的处理,只有等到需要调用 ProcessArray 对象的 process 方法时,才真正传入一个 Command 对象,才确定对数组的处理行为。

PrintCommand.java:

package zhangke.CommandMode;
public class PrintCommand implements Command{
  public void process(int[] target){
    for(int tmp : target){
      System.out.println("迭代输出目标数组的元素: "+tmp);
    }
  }
}

AddCommand.java:

package zhangke.CommandMode;
public class AddCommand implements Command{
  public void process(int[] target){
    int sum = 0;
    for( int tmp : target){
      sum+=tmp;
    }
    System.out.println("数组元素总和是:"+sum);
  }
}

对于 PrintCommand 和 AddCommand 两个类实现类而言,实际有意义的部分就是 process(int[] target)方法,该方法的方法体就是传入 ProcessArray 类里的 process 方法的“处理行为”,通过这种方式就可以实现 process 方法和“处理行为”的分离。

CommandTest.java:

package zhangke.CommandMode;
public class CommandTest{
  public static void main(String[] args){
    ProcessArray pa = new ProcessArray();
    int[] target = {3,-4,6,4};
    pa.process(target,new PrintCommand());
    System.out.println("---------------------");
    pa.process(target,new AddCommand());
  }
}

两次不同的处理行为是通过 PrintCommand 类和 AddCommand 类提供的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值