读书学习笔记~后面是自己一些总结
简单工厂模式原理就是面向接口编程
接口体现的是一种规范和实现分离的设计哲学,充分利用接口可以极好地降低各模块之间的耦合,从而提供系统的可扩展性和可维护性
基于这种原则,很多软件架构设计理论都倡导“面向接口”编程,而不是面向实现类编程,希望通过面向接口编程来降低程序的耦合。
有一个场景,假设程序中有个Computer类需要组合一个输出设备,现在有两个选择:直接让Computer类组合(继承?)一个Print,或者让Computer类组合一个Output,那么到底采用哪种方式更好呢。
假设让Computer类组合一个Printer对象,如果有一天系统需要重构,需要使用BetterPrintrt来代替Printer,这就需要打开Computer类源代码进行修改。如果系统中只有一个Computer类组合了还好,但如果系统中有100个、1000个甚至10000个类组合了Printer,将意味着要对这么多个类进行修改。
为了避免这个问题,工厂模式建议让Computer类组合一个Output类型对象,将Computer类与Print类完全分离。Computer对象实际组合的是printer对象还是BetterPrinter对象,对Computer而言完全透明。当Printer对象切换到BetterPrinter对象时,系统完全不受影响。下面是Computer类的定义代码。
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 Ptinter() ;
}
public static void main (String [ ]args) {
OutputFactory of = new OutputFactory () ;
Computer c = new Computer (of.getOutput) ;
c.keyIn("轻量级Java");
c.keyIn("轻量级Java");
c.print();
}
}
在该OutputFactory类中包含了一个getOutput()方法,该方法返回一个Output实现类的实例,该方法负责创建Output实例,具体创建哪一个实现类的对象由该方法决定。如果系统需要将Print改为BetterPrinter实现类,只需让BetterPrinter实现Output接口,并改变OutputFactory类中的getOutput()方法即可。
下面是BetterPrinter实现类的部分代码,BetterPrinter只是对原有的Printer进行简单修改,以模拟系统重构后的改进。
//这个BetterPrinter需要有输入输出的行为,因此需要实现Output的这些方法
public class BetterPrinter implements Output {
private Sting[] printData = new String[MAX];
private int dataNum;
public void out() {
//.......具体的行为
}
public void getData (String mas) {
//.....具体的行为
}
}
下面是接口Output定义的代码
public interface Output {
//接口定义的成员变量只能是常量
int MAX = 50 ;
//接口定义的普通方法只能是public 的抽象方法
void out();
void getData(String msg) ;
//在接口中定义默认方法,需要使用default修饰
default void print(String... msgs) {
for(String msg : msgs) {
System.out.println(msg);
}
}
//在接口中定义类方法,需要使用static修饰
static String staticTest() {
return "接口里的类方法";
}
}
上面的BetterPrinter类也实现了Output接口,因此也可当成Output对象使用,于是只要把OutputFactory工厂类的getOutput()方法中改成 return new BetterPrinter();
通过这种方式,即可把所以生成Output对象的逻辑集中在OutputFactory工厂类中管理,而所有需要使用Output对象的类(Computer类)只需与Output接口耦合,而不是与具体的实现类耦合。即使系统中有很多类使用了Printer对象,只要OutputFactory类的getOutput()方法生成的Output对象是BetterPrinter对象,则他们全部都会改为使用BetterPrinter对象,而所有程序无须修改,只须修改OutputFactory工厂类的getOutput()方法实现即可。
思维方式!!!!
1、Computer类需要完成输入字符串和输出字符串的动作
2、有两种选择,一种是在Computer类组合Printer(Computer和Printer没有继承关系,所以用组合)。就像这样
public class Computer {
private Printer p;
public void keyIn (String msg) {
p.getData(msg) ;
}
public void print() {
p.out;
}
}
但是这样做不好,像输出设备这种经常需要跟换的东西,假如要换成BetterPrinter的话,Computer类又需要去改变它的源代码,其他组合了Printer类的类也要去修改。
因此有另一种选择,给Computer类组合Output类型的对象(它是一个接口,这个接口有所有的输出设备需要用到的动作,即输入字符串还有输出字符串)
3、所以Printer作为实现类,实现Output接口的方法。
4、然后我们需要一个产生实现类实例的类,那就是OutputFactory工厂类了。也负责打印东西
-------参考书籍《疯狂Java讲义》 李刚著