往常痛点
- 下面这段代码,看着没什么问题,利用接口抽象方法规定了gradeName()这个方法,GradeA去实现它,并写自己的逻辑,但是不利于拓展,比如我想加一个GradeB,Application就不能够帮我new出来想要的对象了,所以我们要改造一下,让我们new出自己想要的对象。
public class GradeA implements GradeNameProvider{
@Override
public void gradeName(){
System.out.println("通信三班");
}
public static void main(String[] args) {
Application application = new Application();
GradeNameProvider obj = application.getGrade();
obj.gradeName();
}
}
interface GradeNameProvider {
abstract void gradeName();
}
class Application{
public GradeNameProvider createGradeA(){
return new GradeA();
}
public GradeNameProvider getGrade(){
return createGrade();
}
}
简单工厂模式
- 这样修改过后,每次新增班级只需要关注工厂类(GradeFactory)就可以了,简化了new对象的流程
- 利用java的多态来实现,降低代码的耦合性。在工厂里生产不同的对象。由此,工厂和产品挂上钩了,联系上了。createGrade生产出来的都是独特的产品。
- 简单工厂模式应该不算是设计模式里的一种,只能说算是一共解决方案
- 结论:最好慎用,违反了设计模式的开闭原则,如果后期增加班级类,需要修改工厂方法
interface GradeNameProvider {
abstract void gradeName();}
public class GradeA implements GradeNameProvider{
@Override
public void gradeName(){
System.out.println("通信三班");
}
}
class GradeB implements GradeNameProvider{
@Override
public void gradeName() {
System.out.println("通信四班");
}
}
class GradeFactory{
public static GradeNameProvider createGrade(String type){
if (type.equals("GradeA")){
return new GradeA();
}else if (type.equals("GradeB")){
return new GradeB();
}else {
throw new RuntimeException("简单工厂里面暂时没有此班级,目前可以new GradeA、GradeB"); }
}
}
class Application{
private GradeNameProvider createGrade(String type){
return GradeFactory.createGrade(type);
}
public GradeNameProvider getGrade(String type){
return createGrade(type);
}
}
class Test{
public static void main(String[] args) {
Application application = new Application();
GradeNameProvider gradeName = application.getGrade("GradeB");
gradeName.gradeName();//通信四班
}
}
工厂模式
- 工厂模式的话肯定是要解决开闭原则这个问题的,不然改动原本代码是大忌,不要从理论上来说不会出问题,实际工作中经常嘴上说着保证没问题,结果上线就出故障。。。
- 工厂模式解决了开闭原则和单一原则,通信三班就做通信三班的事情,不被其他业务打扰,互不干扰。
- 结论:工厂模式还是有缺点的,如果班级类过多,我们就要生成很多的工厂类。假如我们要实现的班级接口不止一个,也就是有多个班级接口,不同班级接口有对应的产品族。什么是产品族呢?简单的理解就是,不同牌子产的车里面会有跑车类型,家庭类型,商用类型等的车,不同牌子的车的跑车类型的车可以组成一个产品族。对于这种情况我们可以采用抽象工厂模式。
我们先改造一下Application这个方法,老代码如下。
class Application{
private GradeNameProvider createGrade(String type){
return GradeFactory.createGrade(type);
}
public GradeNameProvider getGrade(String type){
return createGrade(type); }
}
想要完成开闭原则的改造,首先要拿Application这个方法开刀,把createGrade变为抽象方法,然后新建一个子工厂类实现createGrade,return要生产的对象,说干就干,改造完的方法如下
abstract class Application{
abstract GradeNameProvider createGrade();
public GradeNameProvider getGrade(){
return createGrade();
}
}
想要把createGrade变为抽象方法,先要把Application变为抽象类,我们来测试一下改造过后怎么样,测试代码如下
class Test{
public static void main(String[] args) {
Application application = new Application() {
@Override
GradeNameProvider createGrade() {
return new GradeA();
}
};
GradeNameProvider grade = application.getGrade();
grade.gradeName();//通信三班
}
}
经过上面的测试之后,我们发现没有问题,现在就把GradeA和GradeB改造成工程模式吧!改造完的代码如下
interface GradeNameProvider {
abstract void gradeName();
}
public class GradeA implements GradeNameProvider{
@Override
public void gradeName(){
System.out.println("通信三班");
}
}
class GradeB implements GradeNameProvider{
@Override
public void gradeName() {
System.out.println("通信四班");
}
}
abstract class Application{
abstract GradeNameProvider createGrade();
public GradeNameProvider getGrade(){
return createGrade();
}
}
class ConCreateGradeA extends Application{
@Override
GradeNameProvider createGrade() {
return new GradeA();
}
}
class ConCreateGradeB extends Application{
@Override
GradeNameProvider createGrade() {
return new GradeB();
}
}
我们测试一下工厂模式,代码如下
class Test{
public static void main(String[] args) {
Application application = new ConCreateGradeA();
GradeNameProvider grade = application.getGrade();
grade.gradeName();
}
}
抽象工厂模式
- 抽象工厂模式,很抽象。。。但是不难
- 规定好具体抽象,不同班级产线去实现相应的方法,互不干扰,切换班级只需new不同班级即可。
- CommunicationClassFour这个班级没有我去实现,通信三班已经实现了,通信四班还不好实现吗?只需要实现具体业务的抽象方法即可。小伙伴们可以copy我下面的代码自己去实现一下通信四班
抽象工厂更像是一个工具箱,想要什么东西拿什么,比如MybatisPlus支持很多DB一样,需要什么DB就new什么DB,底层去实现每个DB的逻辑
public class AbstractFactory {
public static void main(String[] args) {
GradeUtils gradeUtils = new CommunicationClassThree();
GradeName grade = gradeUtils.getGradeName();
grade.grade();//这里是通信三班
GradeStudentName gradeName = gradeUtils.getGradeStudentName();
gradeName.name();//这里假装是一个通信三班班级的List
}
}
interface GradeName{
void grade();
}
class CommunicationClassThreeName implements GradeName{
@Override
public void grade() {
System.out.println("这里是通信三班");
}
}
interface GradeStudentName{
void name();
}
class CommunicationClassThreeStudentName implements GradeStudentName{
@Override
public void name() {
System.out.println("这里假装是一个通信三班班级的List");
}
}
interface GradeUtils{
GradeName getGradeName();
GradeStudentName getGradeStudentName();
}
class CommunicationClassThree implements GradeUtils{
@Override
public GradeName getGradeName() {
return new CommunicationClassThreeName();
}
@Override
public GradeStudentName getGradeStudentName() {
return new CommunicationClassThreeStudentName();
}
}