开始
我们有一个Animal接口和它的几个实现类(如Dog和Cat)。如果我们想要创建这些动物的实例,我们可能会直接调用它们的构造函数
// 客户端代码
public class Client {
public static void main(String[] args) {
Animal dog = new Dog();
dog.printName(); //小狗
Animal cat = new Cat();
cat.printName(); //小猫
}
}
// Animal 接口
interface Animal {
void printName();
}
// Dog 类实现 Animal 接口
class Dog implements Animal {
@Override
public void printName() {
System.out.println("小狗");
}
}
// Cat 类实现 Animal 接口
class Cat implements Animal {
@Override
public void printName() {
System.out.println("小狗");
}
}
当我们的系统中有很多这样的动物类时,或者当我们需要根据一些条件动态地创建这些动物时,直接调用构造函数就会变得不灵活且难以维护。这时,我们可以使用工厂模式来改进这种情况。
工厂模式
简单工厂模式
//Animal 接口和 Dog、Cat 类与之前相同。
// AnimalFactory 简单工厂类
public class AnimalFactory {
public static Animal createAnimal(String type) {
if ("dog".equalsIgnoreCase(type)) {
return new Dog();
} else if ("cat".equalsIgnoreCase(type)) {
return new Cat();
} else {
throw new IllegalArgumentException("Invalid Animal type");
}
}
}
//客户端代码
public static void main(String[] args) {
Animal dog = AnimalFactory.createAnimal("dog");
dog.printName(); //小狗
Animal cat = AnimalFactory.createAnimal("cat");
cat.printName(); //小猫
}
可以看到我们创建了一个AnimalFactory类,它有一个静态方法createAnimal,该方法接受一个字符串参数(表示要创建的动物的类型),并返回相应的动物实例。客户端代码现在不再直接调用构造函数,而是使用AnimalFactory来创建动物实例。这样,如果我们需要添加新的动物类型,我们只需要在工厂类中添加相应的逻辑,而不需要修改客户端代码。
简单工厂模式就是:由一个工厂类根据传入的参数来决定创建哪一种产品类的实例。
工厂方法模式
我们不再有一个集中的工厂类来创建所有类型的动物。相反,我们为每个动物类型创建了一个专门的工厂类(DogFactory和CatFactory),它们都实现了AnimalFactory接口。这样,当我们需要添加新的动物类型时,我们只需要创建一个新的工厂类,而不需要修改现有的工厂类或客户端代码。
// AnimalFactory 接口
interface AnimalFactory {
Animal createAnimal();
}
// DogFactory 实现 AnimalFactory 接口,用于创建 Dog
class DogFactory implements AnimalFactory {
@Override
public Animal createAnimal() {
return new Dog();
}
}
// CatFactory 实现 AnimalFactory 接口,用于创建 Cat
class CatFactory implements AnimalFactory {
@Override
public Animal createAnimal() {
return new Cat();
}
}
//客户端
public static void main(String[] args) {
AnimalFactory dogFactory = new DogFactory();
Animal dog = dogFactory.createAnimal();
dog.printName(); //小狗
AnimalFactory catFactory = new CatFactory();
Animal cat = catFactory.createAnimal();
cat.printName();//小猫
}
工厂方法模式提供了更好的扩展性,因为它允许子类决定实例化哪个类。同时,它也比简单工厂模式更加灵活,因为它避免了在工厂类中使用条件语句来判断应该创建哪个对象。然而,这也增加了系统的复杂性,因为需要为每种产品都编写一个工厂类。
抽象工厂模式
使用抽象工厂模式来改造上述动物创建的例子,我们要引入一个更高级别的抽象,即“产品族”的概念。在动物创建的上下文中,我们可以将“狗”和“狗的相关产品”看作是一个产品族,同样,“猫”和“猫的相关产品”也可以看作是一个产品族。
// Animal 接口与之前相同...
// 假设还有与动物相关的其他产品,如食物
interface AnimalFood {
void describe();
}
// 狗的食物实现
class DogFood implements AnimalFood {
@Override
public void describe() {
System.out.println("小狗喜欢吃骨头");
}
}
// 猫的食物实现
class CatFood implements AnimalFood {
@Override
public void describe() {
System.out.println("小猫喜欢吃鱼");
}
}
接下来,我们定义抽象工厂接口和它的实现:
// 抽象工厂接口,用于创建产品族
public interface AnimalFactory {
Animal createAnimal();
AnimalFood createAnimalFood();
}
//猫产品族的工厂实现
public class CatFactory implements AnimalFactory {
@Override
public Animal createAnimal() {
return new Cat();
}
@Override
public AnimalFood createAnimalFood() {
return new CatFood();
}
}
//狗产品族的工厂实现
public class DogFactory implements AnimalFactory {
@Override
public Animal createAnimal() {
return new Dog();
}
@Override
public AnimalFood createAnimalFood() {
return new DogFood();
}
}
客户端实现
public static void main(String[] args) {
// 创建狗产品族的工厂
AnimalFactory dogFactory = new DogFactory();
Animal dog = dogFactory.createAnimal();
dog.printName(); //小狗
AnimalFood dogFood = dogFactory.createAnimalFood();
dogFood.describe(); //小狗喜欢吃骨头
// 创建猫产品族的工厂
AnimalFactory catFactory = new CatFactory();
Animal cat = catFactory.createAnimal();
cat.printName(); //小猫
AnimalFood catFood = catFactory.createAnimalFood();//小猫喜欢吃鱼
有一个抽象工厂接口AnimalFactory,它负责创建动物和动物食物这两种产品。然后,我们有两个具体的工厂实现类(DogProductFactory和CatProductFactory),分别对应狗产品族和猫产品族。客户端代码使用这些具体的工厂来创建并操作属于不同产品族的对象。
抽象工厂模式允许客户端在不知道具体实现类的情况下,使用一组相互关联的产品族中的对象。这增加了系统的灵活性和可扩展性,同时也符合开闭原则(对扩展开放,对修改封闭)。
总结
无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们的目的都是为了解耦,所以,在使用工厂模式时,我们更关心的是降低耦合度的目的是否达到了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。