这一章讲的是简单工厂模式和工厂方法模式的比较。
先是说,小菜有个同学薛磊风(学雷锋),平时默默无闻,一天不幸出了车祸,然后同学们就去医院看望他,才知道他三年如一日地为一位孤寡老人做好事,然后他现在住院了嘛,就拜托小菜他们替他照顾一下老人家。
坦白讲呢,如果是我的话,我做不到这么伟大,我只想照顾好自己的家人就够了。
然后呢,小菜和大鸟说了这个事情,他们就开始谈论设计模式了,今天讨论的是简单工厂和工厂方法模式。
简单工厂就是第一章讲的那个,在工厂类中有switch来生成对应的运算子类,而工厂方法模式呢,是在抽象工厂下面又扩展了对应的加减乘除四个工厂,有什么区别呢?
在简单工厂中,如果要新增运算,那么就要修改工厂类,增加switch的分支,这就违背了开-闭原则,而工厂方法中,新增运算是新增对应的运算工厂类,这样不违背开闭原则。
简单工厂模式最大的优点是工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态的实例化相关的类,对于客户端来说,去除了与具体产品相关的依赖。比如计算器例子中,客户端不用管该用哪个类的实例,只需要把运算符传给工厂就行。但是不可避免的违背了开闭原则,因为新增运算符势必需要修改工厂类。
下面来重点理解一下工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪个子类,把一个类的实例化延迟到子类中。
工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法模式把简单工厂的内部判断逻辑移到了客户端中,你想要增加功能,本来是改工厂类,现在是修改客户端。
回到这一章的故事上来,用代码来表示帮助老人这个故事:
/***
* 雷锋抽象类
*/
public abstract class LeiFeng {
// 扫地
abstract void sweep();
// 洗衣服
abstract void wash();
// 买米
abstract void buyRice();
}
现在三个学生去做好事,学生类Student继承LeiFent,在客户端中这样调用:
public static void main(String[] args) {
LeiFeng student1 = new Student();
LeiFeng student2 = new Student();
LeiFeng student3 = new Student();
student1.sweep();
student2.wash();
student3.buyRice();
}
如果此时这三个不是学生,而是志愿者,那么就需要修改每个new Student()的地方,改成new Volunteer(),
如果用简单工厂来描述,就是:
switch
"学生" :
new Student();
break;
"志愿者":
new Volunteer();
break;
每个实例化学生的地方,都要写Factory.createLeiFeng("学生"),如果需要改成志愿者,那么每个地方都要修改;
而如果用工厂方法模式来描述这个例子,就是:
先创建StudentFactory和VolunteerFactory两个工厂类,继承LeiFengFactory,在客户端中:
LeiFengFactory leiFengFactory = new StudentFactory();
LeiFeng leiFeng1 = leiFengFactory.createLeiFeng();
LeiFeng leiFeng2 = leiFengFactory.createLeiFeng();
LeiFeng leiFeng3 = leiFengFactory.createLeiFeng();
leiFeng1.buyRice();
leiFeng2.sweep();
leiFeng3.wash();
这样,如果要改成志愿者做好事,那么只需要修改new StudentFactory()为new VolunteerFactory(),只需要改这一个地方就行。
工厂方法模式比简单工厂要高明一点,它既封装了创建对象的过程,又克服了开闭原则,缺点是每加一个产品,就要对应增加一个工厂类。 -- “反射,可以解决这个问题。”
网友评论