往常痛点
- 下面这段代码,看着没什么问题,利用接口抽象方法规定了gradeName()这个方法,GradeA去实现它,并写自己的逻辑,但是不利于拓展,比如我想加一个GradeB,Application就不能够帮我new出来想要的对象了,所以我们要改造一下,让我们new出自己想要的对象。
public class GradeA implements GradeNameProvider{@Overridepublic 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{@Overridepublic void gradeName(){System.out.println("通信三班");}}class GradeB implements GradeNameProvider{@Overridepublic 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() {@OverrideGradeNameProvider createGrade() {return new GradeA();}};GradeNameProvider grade = application.getGrade();grade.gradeName();//通信三班}}
经过上面的测试之后,我们发现没有问题,现在就把GradeA和GradeB改造成工程模式吧!改造完的代码如下
interface GradeNameProvider {abstract void gradeName();}public class GradeA implements GradeNameProvider{@Overridepublic void gradeName(){System.out.println("通信三班");}}class GradeB implements GradeNameProvider{@Overridepublic void gradeName() {System.out.println("通信四班");}}abstract class Application{abstract GradeNameProvider createGrade();public GradeNameProvider getGrade(){return createGrade();}}class ConCreateGradeA extends Application{@OverrideGradeNameProvider createGrade() {return new GradeA();}}class ConCreateGradeB extends Application{@OverrideGradeNameProvider 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{@Overridepublic void grade() {System.out.println("这里是通信三班");}}interface GradeStudentName{void name();}class CommunicationClassThreeStudentName implements GradeStudentName{@Overridepublic void name() {System.out.println("这里假装是一个通信三班班级的List");}}interface GradeUtils{GradeName getGradeName();GradeStudentName getGradeStudentName();}class CommunicationClassThree implements GradeUtils{@Overridepublic GradeName getGradeName() {return new CommunicationClassThreeName();}@Overridepublic GradeStudentName getGradeStudentName() {return new CommunicationClassThreeStudentName();}}
