Java抽象类:案例、特点、模板方法模式
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
一.抽象类的案例
案例加油站支付卡
系统需求
某加油站推出了2种支付卡
1、预存1万元的金卡后续加油享受8折优惠
2、预存5千元的银卡后续加油享受8.5折优惠。
请分别实现2种卡片进入收银系统后的逻辑卡片需要包含主人的名称、金额、支付功能。
分析实现
1、创建一个卡片类作为父类属性包含有名称、金额行为包含有支付功能由于2种卡片的加油优惠都不一样因此需定义为抽象方法让2种卡片的子类自己来完成各自的需求由于在父类中定义了抽象方法所以此类也要声明为抽象类
2、创建一个金卡类作为子类继承父类卡片类继承后需重写父类中的全部抽象方法实现预存为1万元后续加油支付将享受8折的优惠
3、创建一个银卡类作为子类继承父类卡片类继承后需重写父类中的全部抽象方法实现预存5千元后续加油支付将享受8.5折的优惠
4、创建一个测试类分别模拟创建2种卡的主人传入姓名、金额后使用各自子类的支付功能完成支付。
父类部分
//创建一个卡片类作为父类由于在父类中定义了抽象方法所以此类也要声明为抽象类
public abstract class Card {
private String userName;
private double money;
//行为包含有支付功能由于两种卡片的加油优惠不一样因此需要定义为抽象方法让两种卡片的子类字节来完成各自的需求
public abstract void pay(double meney2);
//提供成员变量对应的getter、setter方法暴露其取值和赋值
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
}
金卡子类
public class GoldCard extends Card {
@Override
public void pay(double meney2) {
System.out.println("您当前消费"+meney2);
System.out.println("您当前的卡片余额是"+getMoney());
//给出优惠价
double rs = meney2*0.8;
System.out.println("您的实际支付是"+rs);
//更新余额
setMoney(getMoney()-rs);
}
}
银卡子类
public class SliverCard extends Card{
@Override
public void pay(double meney2) {
System.out.println("您当前消费"+meney2);
System.out.println("您当前的卡片余额是"+getMoney());
//给出优惠价
double rs = meney2*0.85;
System.out.println("您的实际支付是"+rs);
//更新余额
setMoney(getMoney()-rs);
}
}
测试类
public class Test {
public static void main(String[] args) {
GoldCard c = new GoldCard();
c.setMoney(10000);
c.setUserName("kk");
c.pay(300);
System.out.println("剩余"+c.getMoney());
System.out.println("--------------------");
SliverCard s = new SliverCard();
s.setMoney(5000);
s.setUserName("tt");
s.pay(300);
System.out.println("剩余"+s.getMoney());
}
}
运行截图
二抽象类的特征和注意事项小结
类有的成员成员变量、方法、构造器抽象类都具备
抽象类中不一定有抽象方法有抽象方法的类一定是抽象类
一个类继承了抽象类必须重写完抽象类的全部抽象方法否则这个类也必须定义成抽象类
不能用abstract关键字修饰变量、代码块、构造器
重要得到了抽象方法失去了创建对象的能力有得有失为什么
// 为什么抽象类不能创建对象
// 反证法假如抽象类可以创建对象
// 这句代码就会可行 Animal a = new Animal();
// 那当调用抽象方法可行吗——> a.run(); // 我们现在学过抽象类所以都知道抽象方法是没有方法体的因此不能创建对象
三final和abstract之间的关系
互斥关系
abstract定义的抽象类是作为模板让子类继承final定义的类不能被继承
细细区分
先想想 final修饰的类是不是就绝育了因此不能被继承也就是不可能有儿子子类
再想想 abstract修饰的类是必须要被继承的因此是一定有儿子子类的
一个不能有儿子一个必须有儿子
再想想 final修饰的方法为最终方法因此不能被重写
再想想 abstract修饰的方法则不是最终方法而且作为模板让子类实现此方法功能因此必须被重写
一个不能重写一个必须重写
结论这俩就是对头关系老死不相往来
四抽象类的应用知识模板方法模式
1.模板方法模式的应用场景
说明当系统中出现一个功能多处开发而该功能中大部分代码是一样的只是其中部分可能不同的时候
模板方法模式实现步骤
把功能定义成一个所谓的模板方法放在抽象类中模板方法中只定义通用且能确定的代码
模板方法中就是不能确定的功能定义成抽象方法让具体子类去实现。
2.案例写作文
通过写作文案例来理解模板方法模式的思想和设计方案
需求
- 现在有两类学生分别是中学生、小学生他们都要写《我的爸爸》这篇作文
- 要求每种类型的学生标题第一段和最后一段内容必须一样正文部分自己发挥
- 请选择最优的面向对象方案进行设计。
/*
1.创建学生类作为父类修饰为抽象类让子类继承。
*/
public abstract class Student {
//作文模板方法标题、开头、正文、结尾
public void write(){
System.out.println("\t\t\t\t《我的爸爸》");
System.out.println("\t我的爸爸是一个让我害怕又让我喜欢的人。");
System.out.print(text());
System.out.println("\n\t因为有了爸爸的爱所以我变得坚强无比因为我的爸爸很牛\n开车不看红绿灯的下辈子我还要做他的儿子。。。");
}
//定义正文部分为抽象方法让子类自己发挥
public abstract String text();
}
/*
2、创建小学生类作为子类继承父类学生类
*/
public class Pupil extends Student{
//重写方法
@Override
public String text() {
return "\t他的台灯不仅仅照着书房....\n\t也照着全省的万家灯火";
}
}
/*
3、创建中学生类作为子类继承父类学生类
*/
public class JuniorSchoolStudent extends Student{
//重写方法
@Override
public String text() {
return "\t他是家里的顶梁柱保护我的成长....";
}
}
/*
4.创建测试类
目标理解模板方法模式的思想和设计方案
*/
public class TemplateTest {
public static void main(String[] args) {
//分别创建中小学生的对象
Pupil p = new Pupil();
JuniorSchoolStudent j = new JuniorSchoolStudent();
//调用方法输出他们写好的作文
System.out.println("小学生的作文");
p.write();
System.out.println("\n--------------------------------------");
System.out.println("中学生的作文");
j.write();
}
}
运行结果
3.模板方法建议用final修饰
这样会更专业因为 模板方法是给子类直接使用的不是让子类重写的一旦子类重写了模板方法则失效了因此加上final后可以防止子类重写模板方法这样更安全、严谨、优雅、专业
4、案例总结
模板方法模式解决了什么问题
- 提高了代码的复用性
- 模板方法已经定义了通用结构模板方法不能确定的部分定义成抽象方法交个子类实现因此使用者只需要关心自己需要实现的功能即可。