概念
简单工厂、抽象工厂和工厂方法都是创建型设计模式,它们都与对象创建相关,但它们之间存在一些区别:
-
简单工厂模式(Simple Factory Pattern):简单工厂模式又称为静态工厂方法模式,是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式实现简单,但是如果要添加新的产品,就需要修改工厂类的代码,违反了“开闭原则”。
-
工厂方法模式(Factory Method Pattern):工厂方法模式定义了一个抽象的工厂类,具体的工厂类负责创建具体的产品对象,每个工厂类只负责创建单一的产品。这样每次添加新的产品,只需要添加一个新的具体工厂类即可。工厂方法模式符合“开闭原则”。
-
抽象工厂模式(Abstract Factory Pattern):抽象工厂模式定义了一个抽象工厂接口,用于创建一组相关或者相互依赖的对象。抽象工厂模式可以同时创建多个对象,与工厂方法模式的区别是,工厂方法模式只能创建一个对象,而抽象工厂模式可以创建多个对象。
总之,三种工厂模式都是为了解决对象创建问题而提出的。简单工厂模式实现简单,但是不符合开闭原则,违反了“对扩展开放,对修改关闭”的设计原则;工厂方法模式可以避免修改原有代码,但是需要为每个产品定义一个工厂类,增加了类的数量;抽象工厂模式适用于创建一组相关的产品对象。
例子
简单工厂模式
假设有两个形状类:Circle(圆形)和 Square(正方形),它们都实现了一个形状接口 Shape。我们现在需要一个形状工厂,根据不同的参数来创建不同的形状对象。
首先,定义 Shape 接口:
public interface Shape {
void draw();
}
然后,定义两个形状类:
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Circle.draw()");
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Square.draw()");
}
}
最后,定义一个形状工厂类 ShapeFactory,根据传入的参数来创建不同的形状对象:
public class ShapeFactory {
public static final String CIRCLE = "circle";
public static final String SQUARE = "square";
public static Shape getShape(String shapeType) {
if (shapeType == null) {
return null;
}
if (shapeType.equalsIgnoreCase(CIRCLE)) {
return new Circle();
} else if (shapeType.equalsIgnoreCase(SQUARE)) {
return new Square();
}
return null;
}
}
现在,我们可以通过调用 ShapeFactory.getShape() 方法来获取不同的形状对象:
Shape circle = ShapeFactory.getShape("circle");
circle.draw(); // 输出 "Circle.draw()"
Shape square = ShapeFactory.getShape("square");
square.draw(); // 输出 "Square.draw()"
以上就是一个简单工厂模式的 Java 实现。注意,这个简单工厂模式的实现只适用于创建形状对象,如果需要创建其他类型的对象,就需要创建新的工厂类。
工厂方法模式
工厂方法模式是一种常见的创建型设计模式,其定义了一个用于创建对象的接口,但是由子类决定要实例化的类是哪一个,也就是说,工厂方法模式将实例化的任务委托给了子类。
下面是一个工厂方法模式的例子:假设我们有一个披萨店,有不同口味的披萨,例如芝士披萨、蛤蜊披萨、意大利香肠披萨等等,我们需要根据不同的口味创建不同的披萨。
首先,定义一个披萨接口:
public interface Pizza {
void prepare();
void bake();
void cut();
void box();
}
然后,定义具体的披萨类:
public class CheesePizza implements Pizza {
@Override
public void prepare() {
System.out.println("准备芝士披萨");
}
@Override
public void bake() {
System.out.println("烘焙芝士披萨");
}
@Override
public void cut() {
System.out.println("切芝士披萨");
}
@Override
public void box() {
System.out.println("装箱芝士披萨");
}
}
public class ClamPizza implements Pizza {
@Override
public void prepare() {
System.out.println("准备蛤蜊披萨");
}
@Override
public void bake() {
System.out.println("烘焙蛤蜊披萨");
}
@Override
public void cut() {
System.out.println("切蛤蜊披萨");
}
@Override
public void box() {
System.out.println("装箱蛤蜊披萨");
}
}
public class PepperoniPizza implements Pizza {
@Override
public void prepare() {
System.out.println("准备意大利香肠披萨");
}
@Override
public void bake() {
System.out.println("烘焙意大利香肠披萨");
}
@Override
public void cut() {
System.out.println("切意大利香肠披萨");
}
@Override
public void box() {
System.out.println("装箱意大利香肠披萨");
}
}
接下来,定义披萨工厂接口:
public interface PizzaFactory {
Pizza createPizza();
}
然后,定义不同口味的披萨工厂的具体实现类:
public class CheesePizzaFactory implements PizzaFactory {
@Override
public Pizza createPizza() {
return new CheesePizza();
}
}
public class ClamPizzaFactory implements PizzaFactory {
@Override
public Pizza createPizza() {
return new ClamPizza();
}
}
public class PepperoniPizzaFactory implements PizzaFactory {
@Override
public Pizza createPizza() {
return new PepperoniPizza();
}
}
抽象工厂模式 例1
下面是一个 Java 实现抽象工厂模式的例子:
假设我们需要开发一个游戏,游戏中有两个角色:魔法师(Magician)和战士(Warrior),每个角色都可以穿不同的装备:铠甲(Armor)和魔法棒(Wand)。
首先,定义两个角色接口 Magician 和 Warrior:
public interface Magician {
void cast();
}
public interface Warrior {
void attack();
}
然后,定义两个装备接口 Armor 和 Wand:
public interface Armor {
void defend();
}
public interface Wand {
void wave();
}
接下来,定义两个角色的具体实现类 MagicianImpl 和 WarriorImpl:
public class MagicianImpl implements Magician {
@Override
public void cast() {
System.out.println("Magician casts a spell");
}
}
public class WarriorImpl implements Warrior {
@Override
public void attack() {
System.out.println("Warrior swings a sword");
}
}
再定义两个装备的具体实现类 ArmorImpl 和 WandImpl:
public class ArmorImpl implements Armor {
@Override
public void defend() {
System.out.println("Armor defends the character");
}
}
public class WandImpl implements Wand {
@Override
public void wave() {
System.out.println("Wand waves and casts magic");
}
}
最后,定义一个抽象工厂接口 GameFactory,该接口有两个方法,分别用于创建 Magician 和 Warrior 以及对应的装备:
public interface GameFactory {
Magician createMagician();
Warrior createWarrior();
Armor createArmor();
Wand createWand();
}
现在,我们可以定义具体的工厂类来实现 GameFactory 接口,例如,定义一个魔幻游戏工厂 MagicGameFactory,该工厂可以创建魔法师和战士以及对应的装备:
public class MagicGameFactory implements GameFactory {
@Override
public Magician createMagician() {
return new MagicianImpl();
}
@Override
public Warrior createWarrior() {
return new WarriorImpl();
}
@Override
public Armor createArmor() {
return new ArmorImpl();
}
@Override
public Wand createWand() {
return new WandImpl();
}
}
现在,我们可以使用 MagicGameFactory 来创建角色和装备,并使用它们来玩游戏:
GameFactory factory = new MagicGameFactory();
Magician magician = factory.createMagician();
Warrior warrior = factory.createWarrior();
Armor armor = factory.createArmor();
Wand wand = factory.createWand();
magician.cast(); // 输出 "Magician casts a spell"
warrior.attack(); // 输出 "Warrior swings a sword"
armor.defend(); // 输出 "Armor defends the character"
wand.wave(); // 输出 "Wand waves and casts magic"
以上就是一个抽象工厂模式的 Java 实现。注意,如果需要创建新的角色或装备,可以创建新的具体工厂类来实现 GameFactory 接口。
抽象工厂模式 例2
假设我们需要创建一个电脑工厂,可以生产联想电脑和戴尔电脑,联想电脑包括联想台式机和联想笔记本电脑,戴尔电脑包括戴尔台式机和戴尔笔记本电脑。
首先,定义电脑接口:
public interface Computer {
void printInfo();
}
然后,定义联想电脑和戴尔电脑的具体实现类:
public class LenovoDesktop implements Computer {
@Override
public void printInfo() {
System.out.println("生产联想台式机");
}
}
public class LenovoLaptop implements Computer {
@Override
public void printInfo() {
System.out.println("生产联想笔记本电脑");
}
}
public class DellDesktop implements Computer {
@Override
public void printInfo() {
System.out.println("生产戴尔台式机");
}
}
public class DellLaptop implements Computer {
@Override
public void printInfo() {
System.out.println("生产戴尔笔记本电脑");
}
}
接下来,定义抽象工厂接口:
public interface ComputerFactory {
Computer createDesktopComputer();
Computer createLaptopComputer();
}
然后,定义联想电脑工厂和戴尔电脑工厂的具体实现类:
public class LenovoComputerFactory implements ComputerFactory {
@Override
public Computer createDesktopComputer() {
return new LenovoDesktop();
}
@Override
public Computer createLaptopComputer() {
return new LenovoLaptop();
}
}
public class DellComputerFactory implements ComputerFactory {
@Override
public Computer createDesktopComputer() {
return new DellDesktop();
}
@Override
public Computer createLaptopComputer() {
return new DellLaptop();
}
}
现在,我们可以通过调用不同的电脑工厂的方法来生产不同品牌的电脑:
ComputerFactory lenovoFactory = new LenovoComputerFactory();
Computer desktop = lenovoFactory.createDesktopComputer();
Computer laptop = lenovoFactory.createLaptopComputer();
desktop.printInfo(); // 输出 "生产联想台式机"
laptop.printInfo(); // 输出 "生产联想笔记本电脑"
ComputerFactory dellFactory = new DellComputerFactory();
desktop = dellFactory.createDesktopComputer();
laptop = dellFactory.createLaptopComputer();
desktop.printInfo(); // 输出 "生产戴尔台式机"
laptop.printInfo(); // 输出 "生产戴尔笔记本电脑"
以上就是一个抽象工厂模式的 Java 实现。注意,抽象工厂模式适用于创建一组相关的对象,如果需要创建其他类型的对象,就需要创建新的工厂接口和实现类。
- 参考文档
https://juejin.cn/post/6985870915640770591
https://www.zhihu.com/question/27125796/answer/2313191829?utm_id=0