JAVA面向对象进阶.docx
《JAVA面向对象进阶.docx》由会员分享,可在线阅读,更多相关《JAVA面向对象进阶.docx(34页珍藏版)》请在冰豆网上搜索。
JAVA面向对象进阶
面向对象进阶
整个代码其实就是由结构代码和逻辑代码组成。
在项目设计过程中,一个基本原则是:
设计和实现相分离。
1、抽象类语法规则
在Java中可以定义一些不含方法体的方法,这类的方法体实现交给子类进行实现,这样的方法就是抽象方法。
包含抽象方法的类肯定是抽象类,抽象类中不一定包含抽象方法,可以包含普通方法。
抽象类和抽象方法是通过abstract关键字进行修饰。
有以下规则:
v抽象类中可以没有包含抽象方法。
v如果抽象类中有一个或者多个抽象方法,那么必须声明该类为抽象类。
如果子类没有对父类的抽象方法进行实现,那么子类也必须定义为抽象类。
v没有抽象静态方法,表示不能用abstract和static修饰符连用。
v没有抽象final方法,表示abstract和final不能连用。
v抽象类不能被实例化,如果需要使用该类,那么采用的方式为让其非抽象类的具体子类的一个实例。
抽象类就是将具体实现延迟到子类进行实现。
publicabstractclassAnimal{
privateStringname;
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicfinalvoida(){
System.out.println("---------a---------");
}
publicabstractvoidhappy();//?
?
?
?
?
?
?
publicvoidadd(){
}
}
publicclassDogextendsAnimal{
publicvoidhappy(){
System.out.println(super.getName()+"?
?
?
?
?
?
happy!
!
");
}
}
publicclassBirdextendsAnimal{
publicvoidhappy(){
System.out.println("?
?
?
?
?
?
happy!
!
");
}
}
【小作业:
定义一个Shape类,定义三角形,四边形,求取周长和面积?
利用Abstract】
2、模板模式
话说女娲开始造人了。
只见她拿出一团黄泥,捏个头,捏个身子,捏个手,然后捏个腿。
好了鞭子一挥,一个人就出现了。
目前她需要制作n个人,【男人、女人等】,都得按照同样的工序进行生产。
因此开始造黄种人、白种人、黑种人。
publicclassWhiteMan{
publicvoidcreateHead(){
System.out.println("?
?
?
?
?
?
?
?
!
");
}
publicvoidcreateNose(){
System.out.println("?
?
?
?
?
?
?
?
?
?
!
");
}
publicvoidcreateBody(){
System.out.println("?
?
?
?
?
?
?
?
?
!
");
}
publicvoidcreateHand(){
System.out.println("?
?
?
?
?
?
?
?
!
");
}
publicvoidcreateLeg(){
System.out.println("?
?
?
?
?
?
?
?
!
");
}
publicvoidcreate(){
createHead();
createNose();
createBody();
createHand();
createLeg();
}
}
黄种人...黑种人同样的构建方式。
但是发现其create方法均一样,而且要求构建的方法必须一模一样,不能允许进行修改。
那么如何进行处理。
因此此时抽取模板方法create,同时将共同的行为方法进行定义。
因此出现模板类:
publicabstractclassHumanModel{
protectedabstractvoidcreateHead();//?
?
?
?
?
?
?
?
?
protectedabstractvoidcreateNose();
protectedabstractvoidcreateBody();
protectedabstractvoidcreateHand();
protectedabstractvoidcreateLeg();
publicfinalvoidcreate(){
createHead();
createNose();
createBody();
createHand();
createLeg();
}
}
模板模式优点:
1.封装不变部分,扩展可变部分。
2.提取公共代码,便于维护。
3.行为由父类控制,子类实现。
模板方法使用场所:
模板方法是一个很常用的代码复用平台,用于把不变行为搬移到父类,把可变行为搬移到子类进行实现。
因此
当各个子类有共同的行为方法,并且逻辑结构一致。
可以考虑使用模板方法。
重要复杂的算法,可以把核心算法设计为模板方法,而把周边的相关细节由子类进行实现。
重构代码时,经常会使用模板模式,有时候会通过钩子约束其行为。
到目前为止,人类都比较正常。
但是现在有情况出现,世界太美好了,得处理下。
例如女娲小姐不想让白种人太得瑟,为此造了一些缺手的人员。
那么需要如何进行处理了?
publicabstractclassHumanModel{
protectedabstractvoidcreateHead();//?
?
?
?
?
?
?
?
?
protectedabstractvoidcreateNose();
protectedabstractvoidcreateBody();
protectedabstractvoidcreateHand();
protectedabstractvoidcreateLeg();
protectedbooleanisFlag(){
returnfalse;
}
publicfinalvoidcreate(){
createHead();
createNose();
createBody();
createHand();
if(!
isFlag()){
createLeg();
}
}
}
publicclassWhiteManextendsHumanModel{
privatebooleanflag=false;//?
?
?
?
?
?
?
?
publicbooleanisFlag(){
returnflag;
}
publicvoidsetFlag(booleanflag){
this.flag=flag;
}
publicvoidcreateHead(){
System.out.println("?
?
?
?
?
?
?
?
!
");
}
publicvoidcreateNose(){
System.out.println("?
?
?
?
?
?
?
?
?
?
!
");
}
publicvoidcreateBody(){
System.out.println("?
?
?
?
?
?
?
?
?
!
");
}
publicvoidcreateHand(){
System.out.println("?
?
?
?
?
?
?
?
!
");
}
publicvoidcreateLeg(){
System.out.println("?
?
?
?
?
?
?
?
!
");
}
}
子类的一个行为决定模板调用顺序:
Hook钩子
3、接口
接口用于定义标准。
接口主要为两个不同的类交互提供标准。
【数据库连接】。
v定义接口
publicinterfaceIUsb
v其它类如何使用接口
publicclassComputerimplementsIUsb
implements:
实现,后面只能接接口。
extends :
继承,只能接普通类或者抽象类。
v多实现
publicclassComputerimplementsIUsb,Connection
v接口的语法规则
接口仍是一个类,能够放置属性及方法。
1 接口中成员变量默认都是publicstaticfinal
publicstaticfinalintABC=2;
intABCD=2;
2 接口中方法默认都是public abstract类型
publicvoidusb();
publicabstractvoida();
3 ?
?
?
?
?
?
publicstaticfinal进行修饰的成员变量以及public abstract修饰的方法定义,还可以有内部类【枚举类】。
4 接口没有构造函数,不能被实例化。
5 接口必须通过类来实现它的抽象方法,用implements关键字
6 ?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
7 ?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
publicclassPowerextendsAbstractUSBimplementsIUsb
IUsbusb=newPower();
8 ?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
9 ?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
v接口的用途
接口用于声明实现类所具有的功能。
或者说对外提供服务,不提供实现。
实现由具体的实现类进行实现。
面向接口编程。
接口体现的还是设计和实现相分离的设计原则。
【作业】:
开发这样一个小系统包含以下类:
教员Teacher、学校School、打印机Printer,具体要求如下:
教员、以及学校都具有方法getInfo():
输出详细信息
打印机有打印方法print(Stringcontent);
学校具有属性:
打印机,能够通过学校的打印机打印教员或学校的详细信息//print(Stringcontent)
为刚才完成的系统增加一种新的类型:
学员(Student),具体要求如下:
学员具有getInfo方法,负责输出学员详细信息,能够通过学校的打印机打印学员的详细信息。
编写测试类StudentTest进行测试,要求:
通过学校的打印机打印学员的详细信息
==================================================
升级上述系统,要求:
打印机有多种类型,比如:
黑白打印机、彩色打印机等
学校可能配备其中任意一款打印机,负责打印教员、或者学校的详细信息
采用面向接口编程的方式实现,抽象出Java接口:
publicinterfaceIPrint{
publicvoidprint(Stringcontent);
}
publicclassBlackWhitePrintimplementsIPrint{
publicvoidprint(Stringcontent){
System.out.println("?
?
?
?
?
?
?
?
?
?
?
?
?
?
.....");
System.out.println("?
?
?
?
:
"+content);
}
}
publicclassColorPrintimplementsIPrint{
publicvoidprint(Stringcontent){
System.out.println("?
?
?
?
?
?
?
?
?
?
?
?
?
?
.....");
System.out.println("?
?
?
?
:
"+content);
}
}
publicclassSchool{
publicStringgetInfo(){
return"I‘amaSchool!
";
}
publicSchool(){
}
publicSchool(IPrintprint){
this.print=print;
}
publicIPrintprint;
publicIPrintgetPrint(){
returnprint;
}
publicvoidsetPrint(IPrintprint){
//IPrintp=newColorPrint();
//?
?
|?
?
?
|?
?
?
?
=new?
?
this.print=print;
}
publicColorPrintcolorPrint;//?
?
?
?
publicBlackWhitePrintwhPrint;//?
?
?
?
publicColorPrintgetColorPrint(){
returncolorPrint;
}
publicvoidsetColorPrint(ColorPrintcolorPrint){
this.colorPrint=colorPrint;
}
publicBlackWhitePrintgetWhPrint(){
returnwhPrint;
}
publicvoidsetWhPrint(BlackWhitePrintwhPrint){
this.whPrint=whPrint;
}
}
publicclassTeacherTest{
publicstaticvoidmain(String[]args){
Schoolschool=newSchool();//?
?
?
?
?
?
?
Teachert=newTeacher();//?
?
?
?
?
?
?
?
?
?
?
//school.setPrint(newPrint());//?
?
?
?
?
?
?
?
?
?
//school.getPrint().print(t.getInfo());//?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
school.setWhPrint(newBlackWhitePrint());
school.getWhPrint().print(t.getInfo());
school.setPrint(newAPrint());
school.getPrint().print(t.getInfo());
}
}
4、抽象类和接口区别
共同特征:
v接口和抽象类都不能被实例化,位于继承树的顶端,用于被其它类继承和实现。
v接口和抽象类都可以包含抽象方法,实现接口或者抽象类的子类必须实现这些定义的方法。
如果不实现的话,需要将该类定义为抽象类。
v接口和抽象类都不能定义static修饰的方法。
抽象类如果定义静态方法,那么必须得有方法体。
不同点:
v接口里只能包含抽象方法,不能有具体实现。
但是抽象类既可以有抽象方法,又可以有普通方法。
v接口里不能有构造方法,抽象类可以有构造方法。
v接口里只能定义静态常量属性,不能定义普通属性;抽象类可以定义静态常量属性,也可以定义普通属性。
v一个子类只能继承一个抽象类,那么一个子类实现多个接口。
v接口中不能有初始化块,但是抽象类可以有初始化块。
v接口体现的是一种规范,用于系统与外界交互的窗口。
接口类似于大纲,当一个接口方法发生改变时,将会辐射式地影响整个系统。
接口一旦定义,基本上不能进行改写。
v抽象类体现的是一种模板式设计,一般当做中间产品,已经包括一些实现的方法以及只定义但要延迟到子类进行实现的方法。
不能当做最终产品。
5、单例模式
【设计模式之禅】建议买的书籍
单例模式:
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
使用private修饰构造函数,只能够在当前类去实例化对象。
publicclassHuangDi{
privatestaticHuangDid=null;
privateHuangDi(){
//为什么使用private目的就是为了不产生第二个皇帝,不提供外面实例化的功能。
}
publicstaticHuangDigetInstance(){
if(d==null){//?
?
?
?
?
?
?
?
?
?
d=newHuangDi();
}
returnd;
}
}
publicclassHuangDiTest{
publicstaticvoidmain(String[]args){
//HuangDih3=newHuangDi();//不提供外边实例化对象的功能
HuangDih=HuangDi.getInstance();
HuangDih1=HuangDi.getInstance();
System.out.println(h==h1);
}
}
单例模式是一个比较简单的模式,其定义如下:
Ensureaclasshasonlyoneinstance,andprovideaglobalpointofaccesstoit。
确保某一个类只有一个实例,并且自行实例化并向整个系统提供这个实例。
publicstaticHuangDigetInstance(){
if(d==null){//?
?
?
?
?
?
?
?
?
?
d=newHuangDi();
}
returnd;
}
对于上面的代码,如果在高并发的环境下,当第一个线程执行到d==null时,发现满足条件,开始执行d=newHuangDi();但是就在这一瞬间,第二个线程也执行到d==null时,发现也满足条件,所以也将执行d=newHuangDi();因此最终在我们系统环境中,会产生两个皇帝实例。
解决方式:
publicclassHuangDi{
privatestaticfinalHuangDid=newHuangDi();
privateHuangDi(){
}
//?
?
?
publicstaticHuangDigetInstance(){
returnd;
}
}
饿汉式单例:
对事物比较饥渴,刚开始就实例化一个对象。
privatestaticfinalHuangDid=newHuangDi();
?
?
?
?
?
:
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
synchronized?
?
?
?
。
if(d==null){//?
?
?
?
?
?
?
?
?
?
d=newHuangDi();
}
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
6、简单工厂模式
例子:
有三种人,黄种人、百种人、黑种人。
都有一个功能:
会笑。
女娲当为工厂,此时女娲发布指令给八卦炉(YELLOW),八卦炉将造人,此时将造出的人访问笑的方法。
/**
*?
?
?
?
?
?
?
?
?
?
?
*@authorAdministrator
*
*/
publicabstractclassHuman{
publicabstractvoidsmile();
}
publicclassYHumanextendsHuman{
@Override
publicvoidsmile(){
System.out.println("?
?
?
?
?
......");
}
}
/**
*?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
*@authorAdministrator
*
*/
publicclassHumanFactory{
publicstaticHumancreateHuman(Stringstr){
Humanh=null;
if("Y".equals(str)){
h=newYHuman();
}elseif("W".equals(str)){
h=newWHuman();
}elseif("B".equals(str)){
h=newBHuman();
}else{
System.out.println("?
?
?
?
?
?
?
!
");
}
returnh;
}
}
publicclassNvWa{
publicstaticvoidmain(String[]args){
Humanh=HumanFactory.createHuman("Y");//?
?
«----?
?
h.smile();
YHumany=(YHuman)HumanFactory.createHuman("Y");//?
?
<----?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
y.smile();
}
}
【抽象工厂模式】
【扩展:
】
八卦炉虽然有了,但是只是简单地做初始化工作,通过new达到目的。
但是有需求,对每一个产品对象都需要进行很复杂的初始化工作,例如需要初始化很多属性值,这样造成的结果是工厂类比较臃肿,代码量比较庞大,那么如何扩展该工厂模式达到这目的了?
反射实例化对象:
Classclazz=Class.forName("com.csu.edu.factory.YHuman");//放置的参数值是类所在的路径。
clazz.newInstance();//返回具体的实例对象
|
newYHuman();
publicstaticHumancreateHuman(Classclazz){
Humanh=null;
try{
h=(Human)clazz.newInstance();
}catch(InstantiationExceptione){
e.printStackTrace();
}catch(IllegalAccessExceptione){
e.printStackTrace();
}
}
工厂模式定义:
Defineaninterfaceforcreatinganobject,butletsubclassesdecidewhichclasstoinstantiate。
FactoryMethodletsaclassdeferinstantiationtosubclasses。
工厂模式是new一个对象的替代品