Bank System项目总结
BackSysterm项目总结
2022.3.22
今日学习了抽象类和接口的知识点后,将BackSysterm的架构进行了一次大升级,总结一下从项目最开始的开发到现在技术上的改进。
项目初期:
项目的最初期是在学习了封装继承开始的,在项目构建的时候结合封装继承的知识点创建了实体类entity包里面包含了父类Account里面定义了卡类的基本属性,然后创建了两个子类分别是信用卡类(CreditAccount)和储蓄卡类(SaveAccount)其中各自有自己的特有属性,然后创建了service包里面包含了BackSysterm的业务类(BackService),最后创建了view包里面包含了控制台显示界面的方法,导入了jar包和自己写的一些工具类,至此将当时自己所学的知识全部运用到了里面,项目初期的时候我开始体会了业务类和实体类分离的好处,初学时都是将业务类中的方法全部写在实体类中,发现后期如果增加或者修改某些功能就必须全部推翻重做,扩展性极差,通过业务类和实体类分离的这个架构大大增加了后期扩展和维护的快捷,但是此时我发现还是有不足的地方,虽然我将实体类和业务类分离了,但是我在写业务类方法时都是将具体方法全部写在实体类当中,当时并没有觉得有什么不对,但是随着学习的深入我发现如果我想要将业务类中方法全部升级时,我必须停止业务类的使用并且要全部打翻重做,那么我就想到如果这个项目是正在线上,那么我改多久它就需要停多久,这完全不可行啊。
项目中期:
此时学习完了面向对象中方法的重写和重载以及多态的内容,从多态的三大特性中受益良多,在此再说一下
1.<父类引用>指向<子类对象>
好处:把不同的子类对象都当作父类来看,利用子类对父类方法的重写,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
2.多态应用之方法参数列表写成父类,可以在设计时合并多个子类参数的方法,并且后期具有拓展性
3.方法的返回类型使用父类,经典应用: 简单工厂
对于项目初期的问题在这个时候还是没有得到解决,但是通过上面说到的内容,我对项目进行了一次升级,如下。
1.加入了23种设计模式之一的工厂类,他的使用场景在于有父类,有若干子类,子类需要创建对象十分适合我实体类中对象的创建,他的好处在于可以需要什么,只需要传入一个正确的参数,就可以获取所需要的对象。
2.当我引入工厂类以后,在业务开发时我的用法是这样的
/*默认账户未登录*/ Account creataccount = null; if (password.equals(again) == true) { if (type == 0 || type == 1) { /*利用工厂类优化,本质是方法的返回类型写成父类*/ /*这里会根据传入的Type值传入AccountFactory中然后选择创建何种类型的账户,好处在于 * 以隐藏子类,提高代码的维护性和后期的拓展*/ creataccount = AccountFactory.getAccount(type); creataccount.setPassword(password); creataccount.setName(name); creataccount.setPersonID(personID); creataccount.setEmail(email); accounts[accountsnumber++] = creataccount;
可以看到这里运用的是多态的第三特性,方法的返回类型使用父类,注意??当接收到此时的类以后需要通过get和set方法对其具体赋值,因为在工厂内中只是帮你new一个对象并没有传入参数初始化的所以需要自己动手。
当我会运用工厂类后,我还是很困惑并没有体会到多态这三个点究竟有什么好的地方直到有一晚我在床上自己思考这个问题时,脑子里有一个想法飘过突然就懂了,我在此说一下,最开始我们运用多态的第一个思想父类引用指向子类都说这个思想好我也不知道好在哪里,中举个例子:
Anilmal anilmal =new Cat()
这个满足了父类引用指向子类了吧,但是如果Cat有自己的方法那么父类是不可以调用的,如果非要调用就只有强制类型转换了,此时我更加觉得没啥用处了,还特别麻烦。
但是通过另外一个例子我就理解了其中还有妙处,假如一个业务类 service.move中普通的多态写法就是传入一个交通工具类用instanceof来判断传入的是什么具体类型再写方法,但是这样的话非常的麻烦,如果我新加入了交通工具还是需要在业务类里面改动代码。这个问题的解决办法是在原本的交通工具类中定义move方法,让不同子类根据自己的需求自己重写,那么再次新加一个交通工具,我只需要在新加入的交通工具类中重写方法就可以了,而不用改动父类的代码在运用时只需要 Ver ver =new Car(),此时就可以调用对应的Car的方法了。具体的来说
1.写一个交通工具管理系统 实体类: 交通工具类(父类)Ver 包含的属性:类型 品牌 价格 子类:自行车 飞机 汽车 业务类: Service 包含各种用途(方法) 利用多态思想,为了后期更好地维护和扩展,创建对象的时候我们利用父类引用指向子类 例如:public Ver move(Ver ver){ 一般初学我们这样子写: if(ver instanof ?){ } } 判断出是什么类型然后再写对应类型的方法,这写的真的垃圾,后期怎么扩展还不是要改动业务类。 为了最大程度的实现减少业务类的改动! 我们这样写! public Ver move(Ver ver){ ver.move() } 只需要在父类交通工具类添加一个这样的空方法 public Class Ver(){ pubilc void move(){ } } 然后 自行车 飞机 汽车 这些子类重写他的方法不就搞定了吗!这样的好处在于 就算他吗后期加一个摩托车只需要继承交通工具类 重写方法就可以了!真妙不可言啊! 测试类: 利用多态思想,为了后期更好地维护和扩展,创建对象的时候我们利用父类引用指向子类 Ver ver1 = new Car Service service =new Service() Service.move(ver1) 这个写的好处就在于ver1可以描述Ver类下所有子类
通过上面的例子的综合例子首先可以看到父类引用指向子类的优势,一个ver1就可以代表所有的交通工具类型,指向谁就是谁,理解到这个好处后这个时候再来看看这句话:多态应用之方法参数列表写成父类,可以在设计时合并多个子类参数的方法,并且后期具有拓展性,此时就可以理解到了上面做法的妙处吧,这一句话就概括了,此时多态的三个特性就理解完了,我在实际的项目中其实用的最多的概念是父类引用指向子类还有返回类型是父类也就是简单工厂的使用,对于第二点,多态应用之方法参数列表写成父类,再利用子类方法的重写来覆盖,可以在设计时合并多个子类参数的方法,并且后期具有拓展性,但是一般子类对象中都不会写业务方法的,所以用的比较少,但是一定要理解这个点。
项目后期:
项目的前期和中期学了 封装 继承 多态 方法重写 方法重载我也在项目中都用到了,后期的话学了static修饰符 final修饰符 抽象类 和接口,这里提下static修饰符我利用他的静态属性初始化的时机是类加载的时候,而且只执行一次,即不会重置这个概念实现了自动生成不重复的id。
最后的最后也就是学完接口和抽象类了,我使用这两个知识点首先将Account类定义为抽象类更符合理解 然后将工厂类中的静态常量定义在了静态常量接口中,工厂类用implements连接静态常量方便了以后的扩展。然后解决了项目初期的疑问,利用接口抽象的定义方法、利用实现类将方法具体的实现。
DAO -- 全名:Data Access Object,数据访问对象(package包名) 下面存放?? 1.数据持久层/数据访问层的``接口``,用来定义各种数据访问方法 2.实现类impl(package包名)--->BaseDaoimpl_实现类名字(实现类)
注意??!!!:
**JDK8.0默认方法*/ default void method2() { System.out.println("接口的默认方法..."); } 默认方法是java8中新添加的方法,其重要作用就是“接口演化”。 假如很久之前创建了一个接口,并且这个接口已经被很多类实现了,但是现在你需要给这个接口中扩展一个新方法A,这就导致前面那些已经实现该接口的类必须要重写这个方法A,否则就不能编译。 而使用默认方法就能很好的解决这个问题,你只需将要扩展的新方法A定义为default,原来的实现子类就不需要重写该方法,现在要实现该接口的子类就可以扩展这个方法了。 /**JDK8.0静态方法*/ public static void method3() { System.out.println("接口中的静态方法"); } 接口静态方法和默认方法类似,只是接口静态方法不可以被接口实现类重写。 接口静态方法只可以直接通过静态方法所在的 接口名.静态方法名 来调用。
附上最后的改造结果:
注意??:第一张图的右下角标注写错了,不是实体类是业务类。
对比上面的两张图片,可以发现最后一张图中,我们为业务类和实现类提供了单例模式,然后就是接口定义的改变,对于注册功能来说,如果我想第一张图一样将传入的参数全部写在接口上了那么相当于我们我把注册的方式完全写死了,,即要想使用这个接口就必须有这个定义的参数,这对单一性的比如说账户查询,存款,取款是可以的,但是对于注册这样有多种可能的,最好还是传入一个父类让他来描述所有子类,然后对具体注册账户传入何种参数以及对参数的具体设置都放在业务类中,这个接口的功能就只是完成以某种方式存储注册添加当前帐户,比如可以是以数据库的方式存储,或者以文件的方式存储,不同的实现类可以满足不同的需求的,同时这样定义出的接口才具有通用性,接口只用管我需要实现什么功能,然后具体如何实现不用关心,所以正因为如此,为了更好的扩展性在定义接口的时候必须要仔细的设计和思考,这个功能我应该传入参数还是传入一个父类类型都是有讲究的。
最终的目的就是:让接口具有通用性,在后期升级或者添加新功能时业务类可以最大程度的减少修改,总体的设计框架是不变的,这样才会有良好好的扩展性。
总而言之就是,高内聚,低耦合。增加块之间或者对象之间独立完成本职业务的能力,减少模块或者对象之间相互依赖的程度。