Java学习day21-抽象类(abstract class)和模板设计模式(TemplateMethod)

一、抽象类(abstract class)

1.随着继承层次中一个个新子类的定义,类变的越来越具体,而父类则更一般、更通用。类的设计应该保证父类和子类能够共享特征。有时需要将一个父类设计的非常抽象,以至于它没有具体的实例,这样的类就叫做抽象类。

比如Animal这个类没办法描写其具体的移动方式,只能将所有Animal类和其方法都进行抽象化处理,即不写具体的实现。等到继承到某个具体的动物时,再把方法体进行具体的实现。

2.用abstract关键字来修饰一个类时,这个类就叫做抽象类。

3.同理,用abstract来修饰一个方法时,该方法就叫做抽象方法。(抽象方法:只有方法的声明,没有方法的实现,以“;”结束。例如:abstract int abstractMethod(int a);)

4.抽象类不能被实例化。抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍为抽象类,即只要类中有一个抽象的方法,那么这个类就必须是一个抽象类。

5.不能用abstract修饰属性、私有方法、构造器、静态方法、final的方法。

package day15;

public abstract class Animal {
    public abstract void test();//只要类中有一个抽象方法,那么这个类就必须是一个抽象类
    
    public abstract void move();
}

class Dog extends Animal{
    public void test() {
        // TODO Auto-generated method stub
        
    }
    
    public void move() {
        System.out.println("狗的移动方式是跑");
        
    }        
}

class Fish extends Animal{
    public void test() {
        // TODO Auto-generated method stub
        
    }
    
    public void move() {
        System.out.println("鱼的移动方式是游");
        
    }
}

abstract class Bird extends Animal{//抽象类可以继承抽象类
    public void move() {
        // TODO Auto-generated method stub
        
    }
    
    public abstract void test();
}
package day15;

public class Test {
    public static void main(String[] args) {
        Dog d = new Dog();
        d.move();
        
        Fish f = new Fish();
        f.move();
    }
}

打印结果为:

狗的移动方式是跑
鱼的移动方式是游

问题:1.为什么抽象类不可以使用final关键字声明?

答:final修饰的类是最终的类,不能被继承。而抽象类不能被实例化,是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。

问题:2.一个抽象类中可以定义构造器吗?

答:抽象类可以有构造方法,只是不能直接创建抽象类的实例对象而已。

练习:编写一个Employee类,声明为抽象类,包含如下三个属性:name,id,salay。提供必要的构造器和抽象方法:work()。对于Manager类来说,他既是员工,还有奖金(bonus)的属性。请使用继承的思想,设计CommonEmployee类和Manager类,要求类中提供必要的方法进行属性访问。

package day15;

public abstract class Employee {
    public Employee(){//显示构造器
        
    }
    
    int id;
    String name;
    double salary;
    
    public abstract void work();
}


class CommonEmployee extends Employee{
    
    public void setCommonEmployeeInFo(int id,String name,double salary){
        super.id = id;
        super.name = name;
        super.salary = salary;
    }
    
    public void getCommonEmployeeInFo(){
        System.out.println(super.id);
        System.out.println(super.name);
        System.out.println(super.salary);
    }
    
    public void work() {
        // TODO Auto-generated method stub
        System.out.println("这是一个普通员工");
    }
}


class Manager extends Employee{
    double bonus;
    
    public void setManagerInFo(int id,String name,double salary,double bonus){
        super.id = id;
        super.name = name;
        super.salary = salary;
        this.bonus = bonus;//这是只属于领导的属性,因此用this
    }
    
    public void getManagerInFo(){
        System.out.println(super.id);
        System.out.println(super.name);
        System.out.println(super.salary);
        System.out.println(this.bonus);
    }
    
    public void work() {
        // TODO Auto-generated method stub
        System.out.println("这是一个领导");
    }
}
package day15;

public class Test {
    public static void main(String[] args) {
        CommonEmployee ce = new CommonEmployee();
        ce.work();
        ce.setCommonEmployeeInFo(1007, "小明", 6000);
        ce.getCommonEmployeeInFo();
        
        Manager m = new Manager();
        m.work();
        m.setManagerInFo(2371, "小白", 10000, 6000);
        m.getManagerInFo();
    }
}

打印结果为:

二、模板方法设计模式(TemplateMethod)

抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为模式。

抽象类就像是一个大纲,里面的抽象方法就是每个章节的标题;子类根据这些标题把每个章节细化出来。

解决的问题:

1.当功能内部一部分实现是确定,一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现。

2.编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给其子类实现,就是一种模板模式。

实例:

package day15;
/**
*模板设计模式
*/
public abstract class Templete { public abstract void code(); public final void getTime(){//使用final是创建一个只允许子类使用,但不允许子类重写的方法 long start = System.currentTimeMillis();//返回当前的秒数 code(); long end = System.currentTimeMillis(); System.out.println("code方法执行的时间:" + (end - start)); } } class TestTmp extends Templete{ public void code() { // TODO Auto-generated method stub int k = 0; for(int i = 0; i < 500000; i++){ k += 1; } System.out.println(k);//k显示执行的次数 } }
package day15;

public class Test {
    public static void main(String[] args) {
        
        TestTmp t = new TestTmp();
        t.getTime();
    }
}

打印结果为:

500000
code方法执行的时间:1

猜你喜欢

转载自www.cnblogs.com/su-peng/p/12525962.html