在Java设计模式-工厂模式(1)简单工厂模式 中我们介绍了简单工厂模式,提到了简单工厂模式违背了开闭原则,而“工厂方法模式”是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。
地点
:湖南永州市蓝山县舜河村
作者
:用心笑* 😁 每天开心设计模式系列:
一、前言
1)概述:
工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。
工厂方法模式对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不再负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。
2)角色结构:
抽象工厂(Creator):是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂(Concrete Creator):这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。在上图中有两个这样的角色:BulbCreator与TubeCreator。
抽象产品(Product):工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。在上图中,这个角色是Light。
具体产品(Concrete Product):这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
博主自语
: 说人话就是往上再抽取一层(所以果然是没有什么是加一层不能解决的,一层不行就加两层)😁
还是上次那个问题:
需求:设计一个咖啡店点餐系统。
设计一个咖啡类(Coffee),并定义其两个子类(美式咖啡【AmericanCoffee】和拿铁咖啡【LatteCoffee】);再设计一个咖啡店类(CoffeeStore),咖啡店具有点咖啡的功能。
3)类图关系:
上一文中的简单工厂类图:
工厂方法类图:
之前在简单工厂模式中,CoffeeStore和SimpleCoffeeFactory工厂直接进行关联,那个时候在SimpleCoffeeFactory简单工厂中还需要做一些具体的操作,但是在这里再次进行了一个抽取,将工厂分为了两层,一是抽象工厂,二是具体的实现工厂。再一次做了一个解耦操作。
想了解简单工厂模式点👉Java设计模式-工厂模式(1)简单工厂模式
具体还是看代码实现吧,在看文末比较总结吧😁
二、代码实现
1)Coffce咖啡抽象类(产品抽象类)
public abstract class Coffee { public abstract void addMilk(); public abstract void addSugar(); public abstract String getName(); }
2)AmericanCoffee 、LatteCoffee类(具体产品类)
public class AmericanCoffee extends Coffee { @Override public void addMilk() { System.out.println("给咖啡加奶"); } @Override public void addSugar() { System.out.println("给咖啡加糖"); } @Override public String getName() { return "美式咖啡"; } }
public class LatteCoffee extends Coffee { @Override public void addMilk() { System.out.println("给咖啡加奶"); } @Override public void addSugar() { System.out.println("给咖啡加糖"); } @Override public String getName() { return "拿铁咖啡"; } }
3)CoffeeFactory(抽象工厂类)
public interface CoffeeFactory { Coffee createCoffee(); }
4)AmericanCoffeeFactory、LatteCoffeeFactory类 (具体实现工厂)
public class AmericanCoffeeFactory implements CoffeeFactory { @Override public Coffee createCoffee() { return new AmericanCoffee(); } }
public class LatteCoffeeFactory implements CoffeeFactory { @Override public Coffee createCoffee() { return new LatteCoffee(); } }
5)咖啡店(用具体产品的客户)
public class CoffeeStore { private CoffeeFactory factory; public CoffeeStore(CoffeeFactory factory) { this.factory = factory; } public Coffee orderCoffee(String type) { Coffee coffee = factory.createCoffee(); coffee.addMilk(); coffee.addSugar(); return coffee; } }
6)测试
我们现在来测试一下
public class Client { public static void main(String[] args) { CoffeeStore coffeeStore = new CoffeeStore(new AmericanCoffeeFactory()); Coffee americano = coffeeStore.orderCoffee("americano"); System.out.println(americano.getName()); /** * 给咖啡加奶 * 给咖啡加糖 * 美式咖啡 */ } }
三、总结
3.1、小结:
从上面的代码来看,这完美的解决了简单工厂方法中所违背的”开闭原则“,在这里如果需要再增加新的产品,只需要再写一个具体的实现工厂类就可以了,而不需要对原代码进行修改。
工厂方法模式是简单工厂模式的进一步抽象。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。
3.2、优点:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
- 灵活性增强,对于新产品的创建,只需多写一个相应的具体工厂类。无须对原工厂进行任何修改,满足开闭原则
- 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。
3.3、缺点:
- 类的个数容易过多,增加复杂度
- 增加了系统的抽象性和理解难度
- 抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。(下一篇文章😀持续更新中)
3.4、应用场景:
- 客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。
- 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
- 客户不关心创建产品的细节,只关心产品的品牌
四、自言自语
我也不知道文章写出来是有用还是无用,只是想做一个分享。希望大家能够喜欢并且在这里能有收获。
你好啊,要天天开心哦。下篇文章再见。
此系列还在持续更新中....👉 我一定还会回来的。😁