在上一篇《设计模式之--简单工厂模式》中,遗留了一个问题:如果我们还要创建鱼的对象,那么我就要去添加鱼这个类,然后去更改工厂类,添加创建鱼的对象的方法,那么,这样就违背了面向对象的设计原则:开闭原则(对修改关闭,对扩展开放)。那么,怎么才能既满足添加了新类的需求,又不用去修改代码呢?
工厂方法模式可以解决这个问题,回顾一下昨天简单工厂模式的UML类图:
可以看出是因为动物工厂类和动物类的紧耦合造成了只要添加新的具体动物类就会去修改动物工厂类内部代码以使动物工厂类能够生产出新的具体动物类,从而违背了开闭原则,是因为动物工厂类中写死了工厂就只能生产哪几种动物,那么,想要达到满足开闭原则的要求,就必须需要我们对动物工厂类和动物类之间解耦。那么如何实现呢?
我们可以将动物工厂类写活,再进一步的抽象成一个抽象类,让其子类成为具体的某一个动物的工厂,那么,当我们添加新的具体动物类的时候,只要添加抽象动物工厂类的子类和对应动物类就可以了,UML类图如下:
可以看出,工厂方法模式更加符合我们日常生活人的思维,如果用汽车举例的话,原先的简单工厂模式相当于只有一个规模固定的工厂,这一个工厂生产好多种车,如果想生产新的品牌的车,就要完全改变这个工厂的规模,来重新布置工厂的布局,影响太大;而工厂方法模式相当于,每个品牌的车对应一个工厂,奔驰车厂只生产奔驰车,宝马车厂只生产宝马车,奥迪车厂只生产奥迪车,当要生产新的品牌的车时候,再建造一个工厂就行了,而不用去修改原先的工厂,这样更加符合人的逻辑思维,也一定程度上符合了开闭原则。
接下来是代码实现:
/<span style="font-family: Arial, Helvetica, sans-serif;">/</span>客户端创建对象时采用多态思想。
public class AnimalTest {
public static void main(String[] args) {
// 使用狗工厂创建一个狗对象
AnimalFactory af = new DogFactory();//多态(向上转型)
Animal a = af.createAnimal();
a.eat();
// 使用猫工厂创建一个猫对象
af = new CatFactory();
a = af.createAnimal();
a.eat();
// 使用鱼工厂创建一个鱼对象
af = new FishFactory();
a = af.createAnimal();
a.eat();
}
}
//定义抽象动物工厂类
public abstract class AnimalFactory {
public abstract Animal createAnimal();
}
//定义鱼工厂
public class FishFactory extends AnimalFactory {
@Override
public Animal createAnimal() {
//返回鱼对象
return new Fish();
}
}
//定义狗工厂
public class DogFactory extends AnimalFactory {
@Override
public Animal createAnimal() {
return new Dog();
}
}
//定义猫工厂
public class CatFactory extends AnimalFactory {
@Override
public Animal createAnimal() {
return new Cat();
}
}
//定义抽象动物类
public abstract class Animal {
public abstract void eat();
}
//定义鱼类
public class Fish extends Animal {
@Override
public void eat() {
System.out.println("鱼吃水草");
}
}
//定义猫类
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃老鼠");
}
}
//定义狗类
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
工厂方法模式的使用场合?
(1)当子类型可能会有很多,以后需要不断添加不同的子类实现时。
(2)当一个系统尚在框架设计阶段,还不知道将来需要实例化哪些具体类时。
(3)系统设计之初不需要具体对象的概念(或者说没有具体对象的概念)。
小结:简单工厂模式将创建对象功能交给专门的类去实现,但当生产新对象时必须要修改工厂类代码,违背了开闭原则;工厂方法模式将生产每一种对象都交给一个专门的工厂去实现,当生产新对象时只要添加新的工厂类和对象类就可以了,从而一定程度上符合了开闭原则。
但是,如果需求变了,对于同种对象我要不同规格的,比如对于狗工厂来说,我需要白毛的狗、黑毛的狗、花斑毛的狗,这要怎么样呢?这显然又超出了工厂方法模式的解决范畴,因为要实现这一功能还要去修改类中的代码,又违背了开闭原则。
那么,怎么样才能够做的更好呢?请关注下篇文章:《设计模式之--抽象工厂模式》