工厂方法模式

默认情况下,我们都是直接使用new的方式去创建对象,但是当我们的程序中大量使用这种方式进行创建对象时,如果这个类的构造方法发生了改变,那就要挨个去进行修改。
因此我们可以直接通过工厂来创建对象,这样如果后续要进行修改,只需要修改工厂类中的实现细节即可。

  1. public class App {
  2. public static void main(String[] args) {
  3. Fruit fruit = FruitFactory.getFruit("apple");
  4. System.out.println(fruit);
  5. }
  6. }
  7. class Fruit {
  8. private String name;
  9. public Fruit(String name) {
  10. this.name = name;
  11. }
  12. @Override
  13. public String toString() {
  14. return "Fruit [name=" + name + "]";
  15. }
  16. }
  17. class Apple extends Fruit {
  18. public Apple() {
  19. super("苹果");
  20. }
  21. }
  22. class Orange extends Fruit {
  23. public Orange() {
  24. super("橘子");
  25. }
  26. }
  27. class FruitFactory {
  28. public static Fruit getFruit(String fruitName) {
  29. switch (fruitName) {
  30. case "apple":
  31. return new Apple();
  32. case "orange":
  33. return new Orange();
  34. default:
  35. return null;
  36. }
  37. }
  38. }

这样,根据给工厂类传入的参数不同,就可以创建、获取不同类的对象。
但上述方式也存在一些问题

如果现在要先加一种类型的水果,那么除了要创建一个新的类以外,还要修改工厂类中的代码,这显然是违背了开闭原则

因此我们将代码修改为如下:

创建一个抽象工厂类,来定义一种规则,并使用泛型来约束入参

image.png

具体的工厂类只需要继承这个抽象类,并定义自身的行为即可

image.png

整体代码如下

  1. package code2;
  2. class Fruit {
  3. private String name;
  4. public Fruit(String name) {
  5. this.name = name;
  6. }
  7. @Override
  8. public String toString() {
  9. return "Fruit [name=" + name + "]";
  10. }
  11. }
  12. class Apple extends Fruit {
  13. public Apple() {
  14. super("苹果");
  15. }
  16. }
  17. class Orange extends Fruit {
  18. public Orange() {
  19. super("橘子");
  20. }
  21. }
  22. abstract class FruitFactory<T extends Fruit> {
  23. public abstract T getFruit();
  24. }
  25. class AppleFactory extends FruitFactory<Apple> {
  26. @Override
  27. public Apple getFruit() {
  28. return new Apple();
  29. }
  30. }
  31. class OrangeFactory extends FruitFactory<Orange> {
  32. @Override
  33. public Orange getFruit() {
  34. return new Orange();
  35. }
  36. }
  37. public class App {
  38. public static void main(String[] args) {
  39. // 通过AppleFactory获取Apple对象
  40. Apple apple = new AppleFactory().getFruit();
  41. System.out.println(apple);
  42. }
  43. }

抽象工厂模式

建造者模式

如果某个类中的字段数目太多,那么在手动new创建对象的时候,就会导致需要传递太多参数。

  1. package code3;
  2. public class App2 {
  3. public static void main(String[] args) {
  4. Student student = new Student(1, "yxr", 19, "三峡大学");
  5. System.out.println(student);
  6. }
  7. }
  8. // 省略了构造函数等方法
  9. class Student {
  10. private Integer id;
  11. private String name;
  12. private Integer age;
  13. private String college;
  14. }

为了避免传递过多的参数,并且让方法支持链式调用,我们可以使用建造者模式,通过builder来创建对象