一 前言

经常听说各种设计模式,知道理论,也知道应该使用,但具体怎么用,什么时候用,使用的优点一直比较模糊,今天写一个项目中经常用到的模式,来具体理解。项目中经常用到工厂模式或者策略模式,偶尔也会一起使用来增强代码管理,今天就一起使用来理解。

二 实现

不废话,直接上代码,最后解释
先写一个接口 Person 类

package com.fcy.demo.entity;

public interface Person {
    void eat();
    void run();
}

然后使用策略模式,根据不同的人的类型,创建不同的人,实现该接口,这里有三种类型 Teacher, Doctor, Worker, 首先定义一个常量类,包含这三种类型的人。

package com.fcy.demo.constant;

public class PersonType {
  public static final String TEACHER = "teacher";
  public static final String DOCTOR = "doctor";
  public static final String WORKER = "worker";
}

接着写三种人的实现类

package com.fcy.demo.entity;

import com.fcy.demo.constant.PersonType;
import org.springframework.stereotype.Component;

@Component(PersonType.TEACHER)
public class Teacher implements Person{

  @Override
  public void eat() {
    System.out.println("老师吃");
  }

  @Override
  public void run() {
    System.out.println("老师跑");
  }
}

package com.fcy.demo.entity;

import com.fcy.demo.constant.PersonType;
import org.springframework.stereotype.Component;

@Component(PersonType.DOCTOR)
public class Doctor implements Person{

  @Override
  public void eat() {
    System.out.println("医生吃");
  }

  @Override
  public void run() {
    System.out.println("医生跑");
  }
}

package com.fcy.demo.entity;

import com.fcy.demo.constant.PersonType;
import org.springframework.stereotype.Component;

@Component(PersonType.WORKER)
public class Worker implements Person{

  @Override
  public void eat() {
    System.out.println("工人吃");
  }

  @Override
  public void run() {
    System.out.println("工人跑");
  }
}

到此,为什么使用策略模式呢,因为如果不使用策略模式,所有代码都写在一个实现类里,当用户想让一个老师吃的时候,代码会变得比较繁琐,类似:

public void eat(PersonType type){
	if (PersonType.TEACHER.equals(type)){
		 System.out.println("老师吃");
	} else if (PersonType.DOCTOR.equals(type)){
		 System.out.println("医生吃");
	} else (PersonType.WORKER.equals(type)){
		 System.out.println("工人吃");
	}
}

这里只有三种人,如果有十种甚至更多,会有更多的 if…else…, 同理对 run 操作也会有这么多的判断,实在难以维护,后续对某一类型的 eat 行为做更改时,也会影响其他代码,违背了开闭原则,即对扩展开放,对修改关闭。因此使用策略模式,使不同类型的人实现同一接口,当对某一类型的行为做更改时,不会影响其他类型的代码。
接下来说工厂模式
上面代码中重点是 @Component(PersonType.WORKER), 定义了 @Component 里的参数使得之后使用工厂模式时可以知道工厂该生产那种人。
到此,为什么使用工厂模式呢,如果不使用工厂模式,仅使用策略模式,同理当我想要一个老师吃的时候我需要自己实例一个老师类,类似下面代码:

public void eat(PersonType type){
	if (PersonType.TEACHER.equals(type)){
		Teacher teacher = new Teacher();
		teacher.eat();
	} else if (PersonType.DOCTOR.equals(type)){
		Doctor doctor = new Doctor();
		doctor.eat();
	} else (PersonType.WORKER.equals(type)){
		Worker worker = new Worker();
		worker.eat();
	}
}

虽然我们使用了策略模式,使代码满足开闭原则,易于维护,但并没有解决这么多 if…else… 的问题,所以我们使用工厂模式,减少判断,上代码:

package com.fcy.demo.factory;

import com.fcy.demo.entity.Person;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class PersonFactor {

  @Autowired
  private Map<String, Person> personTypeMap;

  public Person getPerson(String personType) {
    return personTypeMap.get(personType);
  }
}

至此我们就不需要这么多的判断了,当需要某种类型的人时,直接告诉工厂就可以了,controller 代码如下:

package com.fcy.demo.controller;

import com.fcy.demo.entity.Person;
import com.fcy.demo.factory.PersonFactor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/person")
public class PersonController {

  @Autowired
  public PersonFactor personFactor;

  @GetMapping("/teacher")
  public void getTeacher(){
    Person teacher = personFactor.getPerson("teacher");
    teacher.eat();
  }
}

启动代码,访问 http://localhost:8080/person/teacher, 发现控制台输出 “老师吃”, 测试成功,至此代码完成,也可以在 controller 中写其他的方法。

三 总结

在上面中解释了为什么使用 策略模式以及工厂模式,以及使用的优点,还有一个问题没有说,就是什么时候使用该模式, 在一类事物有共同的行为,但行为模式不同时就可以使用。
就到这吧,至此,关于 策略模式与工厂模式有了一个基本理解,也可以实现了。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐