前言
最开始创建对象是用new,就是原始社会要用斧头得自己造
进入工业社会,也就是所说的工厂模式,有了工厂,工厂可以生产斧头,直接可以从工厂买
当然更高级的是控制反转,也叫依赖注入,从配置文件中配置,相当于进入社会主义了,有人直接把斧头送到你手上,对象就这么生成出来了
工厂模式易于功能扩展,例如有个汽车生产工厂,原来有比亚迪产线、大众产线,现在要加一条凯迪拉克产线。只需返回汽车汽车类共有的(父类)凯迪拉克类的对象(此对象是多态对象),而不对其他产线造成影响。
一、工厂模式简介
工厂模式,也叫多态工厂(Polymorphic Factory)模式,属于类创建型模式。
定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
二、代码实现
场景:常见的登录功能,通过不同方式实现登录。下面通过工厂模式+枚举实现。
1.定义一个登录类型枚举
@Getter
@AllArgsConstructor
public enum LoginEnum {
password(Type.PASSWORD, "密码登录"),
sms(Type.SMS, "短信登录"),
scan(Type.SCAN, "扫码登录"),
;
public static class Type {
public static final String PASSWORD = "password";
public static final String SMS = "sms";
public static final String SCAN = "scan";
}
public String loginType;
public String remark;
}
2.定义一个登录接口
public interface LoginService {
String login();
}
3.定义登录实现类
通过@Service
注解以及设置对应的枚举项值,后续通过该枚举项找到对应的实现类。
@Service(LoginEnum.Type.PASSWORD)
public class PasswordLoginService implements LoginService {
@Override
public String login() {
return "密码登录成功!";
}
}
@Service(LoginEnum.Type.SMS)
public class SmsLoginService implements LoginService {
@Override
public String login() {
return "短信登录成功!";
}
}
@Service(LoginEnum.Type.SCAN)
public class ScanLoginService implements LoginService {
@Override
public String login() {
return "扫码登录成功!";
}
}
4.定义登录工厂
通过@Autowired
注解,SpringBoot会自动找到实现LoginService接口的实现类列表。
@Service
public class LoginFactory {
@Autowired
private Map<String, LoginService> serviceMap = new ConcurrentHashMap<>();
public LoginService login(String type) {
return serviceMap.get(type);
}
}
5.测试
@Autowired
private LoginFactory loginFactory;
@Test
public void test() {
String loginPassword = loginFactory.login(LoginEnum.Type.PASSWORD).login();
System.out.println("loginPassword = " + loginPassword);
String loginSms = loginFactory.login(LoginEnum.Type.SMS).login();
System.out.println("loginSms = " + loginSms);
String loginScan = loginFactory.login(LoginEnum.Type.SCAN).login();
System.out.println("loginScan = " + loginScan);
}
输出:
总结
原来创建一个对象是自己new,而现在可以直接通过工厂将我需要的对象直接给我。
调用一个具体的产品对象,只需要知道这个产品的类名和约束参数就可以了,不用知道创建对象自身的复杂过程。降低模块之间的耦合度。