面向接口编程的设计模式
来源:互联网 发布:淘宝909是什么节 编辑:程序博客网 时间:2024/05/01 23:31
面向接口编程的设计模式
简单工厂模式
- 假设程序中有个Computer类需要组合一个输出设备,现在有两个选择:直接让Computer类组合一个Printer,或者让Computer类组合一个Output,那么到底采用哪种方式更好呢?
- 假设让Computer类组合一个Printer对象,如果有一天系统需要重构,需要使用BetterPrinter来代替Printer,这就需要打开
Computer类源代码进行修改。如果系统中只有一个Computer类组合了Printer还好,但如果系统中有100个类组合了Printer,甚至
1000个、10000个……将意味着需要打开100个、1000个、10000个类进行修改,工作量十分巨大。
为了避免上面的问题发生,工厂模式建议让Computer类组合一个Output类型的对象,将Computer类与Printer类完全分离。Computer对象实际组合的是Printer对象还是BetterPrinter对象,对Computer而言完全透明。当Printer对象切换到BetterPrinter时,系统完全不受影响。代码如下:
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工厂类代码如下:
public class OutputFactory { public Output getOutput() { return new Printer(); } public static void main(String[] args) { OutputFactory of = new OutputFactory(); Computer c = new Computer(of.getOutput()); c.keyIn("轻量级Java EE企业应用实战"); c.keyIn("疯狂Java讲义"); c.print(); }}
- 在该OutputFactory类中包含了一个getOutput方法,该方法负责创建Output实例并返回,如果系统需要将Printer改为BetterPrinter实现类,只需要让BetterPrinter实现Output接口,并改变OutputFactory类中的getOutput方法即可。
下面是BetterPrinter实现类的代码,BetterPrinter只是对原有的Printer进行简单修改,以模拟系统重构后的改进。
public class BetterPrinter implements Output { private String[] printData = new String[MAX_CACHE_LINE * 2]; // 用以记录当前需打印的作业数 private int dataNum = 0; public void out() { // 只要还有作业,继续打印 while (dataNum > 0) { System.out.println("高速打印机正在打印:" + printData[0]); // 把作业队列整体前移一位,并将剩下的作业数减1 System.arraycopy(printData, 1, printData, 0, --dataNum); } } public void getData(String msg) { if (dataNum >= MAX_CACHE_LINE * 2) { System.out.println("输出队列已满,添加失败"); } else { // 把打印数据添加到队列里,已保存数据的数量加1。 printData[dataNum++] = msg; } }}
- 上面的BetterPrinter类也实现了Output接口,因此也可当成Output对象使用,于是只要把OutputFactory工厂类的getOutput方法修改即可。
- 再次运行前面的OutputFactory程序,发现系统运行时已经改为BetterPrinter对象,而不再是原来的Printer对象。通过这种方式,即可把所有生成Output对象的逻辑集中在Output工厂类中管理,而所有需要使用Output对象的类只需与Output接口耦合,而不是与具体的实现类耦合。即是系统中有很多类使用了Printer对象,只要OutputFactory类的getOutput方法生的是BetterPrinter对象,则他们全部都会改为使用BetterPrinter对象,而所有程序无需修改每只需要修改OutputFactory工厂类的getOutput方法实现即可。
命令模式
某个方法需要完成某一个行为,但这个行为的具体实现无法确定,必须等到执行该方法时才可以确定。具体一点:假设有个方法需要遍历某个数组的数组元素,但无法确定在遍历时如何处理这些元素,需要在调用该方法时指定具体的处理行为。
这个要求看起来有点奇怪:这个方法不仅需要普通数据可以变化,甚至还有方法执行提也需要变化,难道需要把“处理行为”作为参数传入该方法?
对于这样一个需求,可以考虑使用一个Command接口来定义一个方法,用这个方法来封装“处理行为”。下面是Command接口的代码:
public interface Command { // 接口里定义的process方法用于封装“处理行为” void process(int[] target);}
上面的process方法没有方法体,因为还无法确定这个处理行为。
下面是需要处理数组的处理类,在这个处理类中包含一个process方法,这个方法无法确定处理数组的处理行为,所以使用了一个Command参数,这个参数负责对数组的处理行为。
public class ProcessArray { public void process(int[] target, Command cmd) { cmd.process(target); }}
通过一个Command接口,就实现了让ProcessArray和具体处理行为的分离,程序使用Command接口代表类对数组的处理行为。Command接口也没有提供真正的处理,只有等待需要调用ProcessArray对象的process方法是,才真正传入一个Command对象,才确定对数组的处理行为。
下面程序实现了对数组的两种处理方式:
public class CommandTest { public static void main(String[] args) { ProcessArray pa = new ProcessArray(); int[] target = { 3, -4, 6, 4 }; // 第一次处理数组,具体处理行为取决于PrintCommand pa.process(target, new PrintCommand()); System.out.println("------------------"); // 第二次处理数组,具体处理行为取决于AddCommand pa.process(target, new AddCommand()); }}public class PrintCommand implements Command { public void process(int[] target) { for (int tmp : target) { System.out.println("迭代输出目标数组的元素:" + tmp); } }}public class AddCommand implements Command { public void process(int[] target) { int sum = 0; for (int tmp : target) { sum += tmp; } System.out.println("数组元素的总和是:" + sum); }}
- 面向接口编程的设计模式
- 勃大精深的设计模式--面向接口编程
- Java设计模式_Iterator_面向接口编程
- java策略设计模式,面向接口编程
- 设计模式前篇——面向接口编程
- 策略设计模式(面向接口编程) 案例讲解
- 学习设计模式(1)——面向接口编程
- 设计模式——面向接口编程之柔性多态增强代码的可扩展性
- 设计原则-----------面向接口编程
- 从头认识设计模式-策略模式-05-思考过程四:引入设计原则:面向接口编程
- 面向接口 的编程
- 面向接口的编程
- 面向接口的编程
- 面向接口的编程
- 面向接口编程在工厂模式下的实现
- 面向接口编程(简单工厂模式)和单列设计模式
- 设计模式之接口编程
- 面向接口设计和编程——(面向对象、面向接口、面向过程、面向实现)
- 【linux】history命令详解
- 输入一个年份,判断是否是闰年
- 一个简单的字符串前补0的方法
- STL 算法
- IIS7全新管理工具AppCmd.exe的命令使用
- 面向接口编程的设计模式
- Git SSH Key 生成步骤
- Objective-C自动生成文档工具:appledoc
- gcc和交叉编译头文件包含问题
- 合并排序算法的时间复杂性分析
- 541. Reverse String II (C++)
- zoj 1610 Count the Colors(线段树 区间更新)
- [组合数学] BZOJ 2227 [Zjoi2011]看电影(movie)
- 从USB驱动器运行Windows 10