简单工厂不是设计模式。它只是将对象创建与客户端代码解耦。换句话说,简单工厂通过将实例化逻辑移至单独的类来封装对象实例化。
简单工厂经常与工厂模式混淆。我们将研究简单工厂来阐明它们的区别。另外,学习简单工厂可以帮助我们轻松理解工厂模式。
应避免对具体实现进行编程,因为这会使应用程序非常难以维护。对接口进行编程总是更好的选择。如果您在客户端代码中实例化一个具体类,那么简单工厂会派上用场,因为简单工厂可以将对象创建与客户端分离。这使得我们的应用程序更具可扩展性和可维护性。
我们正在为汉堡店开发系统。系统需要制作牛肉汉堡、鸡肉汉堡等各种汉堡。
我们的第一次尝试是这样的:
// Client orders a burger Burger orderBurger(String type) { Burger burger; if (type.equals("beef")) { burger = new BeefBurger(); } else if (type.equals("chicken")) { burger = new ChickenBurger(); } else if (type.equals("fish")) { burger = new FishBurger(); } burger.prepareBun(); burger.grillPatty(); burger.addToppings(); burger.wrap(); return burger; }
问题是,我们正在针对实现进行编码,而不是针对接口进行编码。在哪里?我们使用 if 语句并根据汉堡类型实例化一个具体类。
为什么会出现这个问题呢?我们的客户端代码与对象创建紧密耦合,导致灵活性降低!假设我们不再销售鱼汉堡,并开始销售素食汉堡。我们需要访问我们的客户端代码并修改它。也就是说不关闭修改。
为了解决这个问题,我们可以创建单独的类,它只负责对象的创建。那么我们的客户端代码就不需要担心对象创建并且能够依赖抽象。这种技术被称为“封装变化的内容”。我们预计有关实例化具体对象的代码将经常更改,而未来所有汉堡中的prepareBun()、grillPatty()、addToppings()、wrap()过程可能会保持不变。
简单工厂的优点是可以被其他类重用。我们可能有其他客户端类,例如 BurgerRestaurant、BurgerCateringShop,它们将使用 SimpleBurgerFactory.createBurger() 方法。
客户
客户端通过SimpleBurgerFactory实例化特定的汉堡对象。请注意,从客户端角度来看,我们不知道将创建哪个具体汉堡,也就是说,对象创建逻辑现在与客户端解耦。
简单汉堡工厂
这个类封装了不同的内容,在本例中是对象创建逻辑! createBurger() 被声明为静态方法,因为客户端想要使用此类来实例化对象(当然,在实例化它之前我们不能有实例!)。 createBurger() 接受 BurgerType 枚举来确定应创建哪种类型的汉堡。
汉堡
这个抽象类提供所有汉堡之间的通用接口并定义默认行为。
汉堡子类
这是我们的具体产品。只要扩展 Burger 类,他们就可以通过重写方法来实现特定行为。
// Client orders a burger Burger orderBurger(String type) { Burger burger; if (type.equals("beef")) { burger = new BeefBurger(); } else if (type.equals("chicken")) { burger = new ChickenBurger(); } else if (type.equals("fish")) { burger = new FishBurger(); } burger.prepareBun(); burger.grillPatty(); burger.addToppings(); burger.wrap(); return burger; }
public enum BurgerType { BEEF, CHICKEN, FISH, VEGGIE }
// Abstract Product public abstract class Burger { public BurgerType burgerType; public List<String> toppings = new ArrayList<>(); public void prepareBun() { System.out.println("Preparing a bun"); } public void grillPatty() { if (burgerType == null) { throw new IllegalStateException("pattyType is undefined"); } System.out.println("Grill a " + burgerType + " patty"); } public void addToppings() { for (String item : toppings) { System.out.println("Add " + item); } } public void wrap() { System.out.println("Wrap a burger up"); } }
// Concrete product public class BeefBurger extends Burger { public BeefBurger() { burgerType = BurgerType.BEEF; List<String> items = List.of("lettuce", "pickle slices", "tomato slice", "BBQ sauce"); toppings.addAll(items); } }
// Concrete product public class VeggieBurger extends Burger { public VeggieBurger() { burgerType = BurgerType.VEGGIE; List<String> items = List.of("smoked paprika", "garlic chips", "crushed walnuts", "veggie sauce"); toppings.addAll(items); } // Concrete product can implement specific behavior that differs from other products @Override public void wrap() { System.out.println("Wrapping paper shouldn't print any meats but vegetables"); } }
// Simple factory, responsible for instantiating an object public class SimpleBurgerFactory { public static Burger createBurger(BurgerType type) { return switch (type) { case BEEF -> new BeefBurger(); case CHICKEN -> new ChickenBurger(); case FISH -> new FishBurger(); case VEGGIE -> new VeggieBurger(); default -> throw new IllegalArgumentException("unknown burger type"); }; } }
输出:
public class Client { public static void main(String[] args) { Burger burger = orderBurger(BurgerType.VEGGIE); System.out.println(burger); // Check if the object is actually veggie burger } public static Burger orderBurger(BurgerType type) { // Factory is responsible for object creation Burger burger = SimpleBurgerFactory.createBurger(type); burger.prepareBun(); burger.grillPatty(); burger.addToppings(); burger.wrap(); return burger; } }
您可以在这里查看所有设计模式的实现。
GitHub 存储库
附注
我是刚开始写科技博客,如果您对我的写作有什么建议,或者有任何困惑的地方,请留言!
感谢您的阅读:)
以上是简单工厂的详细内容。更多信息请关注PHP中文网其他相关文章!