1、抽象类的实际应用 — 定义模板
假设有这样的场景,将人分为工人和学生,两者都能说话,只是说话的内容不一样,换句话说,说话这个功能应该是一个具体功能,说话的内容由学生和工人决定,我们可以用抽象类实现这个场景
abstract class Person2{
private String name;
private int age;
public Person2(String name, int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void say(){
System.out.println(this.getContent());
}
public abstract String getContent();
}
class Student2 extends Person2{
private String school;
public Student2(String name,int age, String school){
super(name, age);
this.setSchool(school);
}
public void setSchool(String school){
this.school = school;
}
public String getSchool() {
return school;
}
public String getContent(){
return "姓名:" + super.getName() + " 年龄:" + super.getAge() + " 学校:" + getSchool();
}
}
class Worker2 extends Person2{
private float salary;
public Worker2(String name, int age, float salary){
super(name, age);
this.salary = salary;
}
public void setSalary(float salary) {
this.salary = salary;
}
public double getSalary() {
return salary;
}
@Override
public String getContent() {
return "姓名:" + super.getName() + " 年龄:" + super.getAge() + " 收入:" + getSalary();
}
}
public class AbstractClassAppDemo {
public static void main(String[] args) {
Student2 stu = new Student2("张三", 20, "NKU");
Worker2 wk = new Worker2("李四",30,8000.0f);
stu.say();
wk.say();
}
}
// 运行结果:
姓名:张三 年龄:20 学校:NKU
姓名:李四 年龄:30 收入:8000.0
2、接口的实际应用 — 制定标准
接口在实际生活中更多的是用来制定标准的,比如U盘和打印机都可以插在电脑上使用,这是因为他们都实现了USB接口,对于电脑来说,只要符合USB接口标准的设备都可以插入使用。
interface USB{
public void start();
public void stop();
}
class Computer{
public static void plugin(USB usb){
usb.start();
System.out.println("============ USB 设备工作 ===========");
usb.stop();
}
}
class Flash implements USB{
public void start(){ // 覆写方法
System.out.println("U盘开始工作");
}
public void stop(){
System.out.println("U盘结束工作");
}
}
class Print implements USB{
public void start() {
System.out.println("打印机开始工作");
}
public void stop() {
System.out.println("打印机结束工作");
}
}
public class AbstractClassAppDemo {
public static void main(String[] args) {
// Student2 stu = new Student2("张三", 20, "NKU");
// Worker2 wk = new Worker2("李四",30,8000.0f);
// stu.say();
// wk.say();
Computer.plugin(new Flash());
Computer.plugin(new Print());
}
}
// 运行结果:
U盘开始工作
============ USB 设备工作 ===========
U盘结束工作
打印机开始工作
============ USB 设备工作 ===========
打印机结束工作
3、工厂设计模式
工厂设计模式是Java里最常见的一种设计模式,我们来看一下这段代码
interface Fruit{ // 定义一个水果接口
public void eat(); // 吃水果
}
class Apple implements Fruit{
public void eat(){
System.out.println("** eat apple!")
}
}
class Orange implements Fruit{
public void eat(){
System.out.println("** eat orange!")
}
}
public class InterfaceDemo{
public static void main(String args[]){
Fruit f = new Apple(); // 实例化接口
f.eat();
}
}
思考:
上面的代码是否有问题?
可以看到,代码的逻辑没有问题,只是这样的设计是否合理呢?主方法我们理解为客户端,主方法里代码自然是越少越好,我们看到在主方法里直接指定了要操作的子类,如果要更换子类,就必须修改客户端,也就是说客户端和子类是耦合的。
interface Fruit{ // 定义一个水果接口
public void eat(); // 吃水果
}
class Apple implements Fruit{
public void eat(){
System.out.println("** eat apple!")
}
}
class Orange implements Fruit{
public void eat(){
System.out.println("** eat orange!")
}
}
class Factory{ // 定义工厂类
public static Fruit getInstance(String className){
Fruit f = null;
if("apple".equals(className)){
f = new Apple();
}
if("orange".equals(className)){
f = new Orange();
}
return f;
}
}
public class InterfaceDemo{
public static void main(String args[]){
Fruit f = Factory.getInstance(args[0]); // 实例化接口
if(f!=null){ // 判断是否获取实例
f.eat();
}
}
}
4、代理设计模式
代理设计模式也是Java里用的比较多的一种设计模式,所谓的代理设计就是指用代理主题来操作真实主题,真实主题执行具体的业务操作,而代理主题则负责其它业务相关的处理。最常见的就是找代理上网,客户端通过网络代理连接网络,由代理服务器完成用户权限,访问限制等与上网相关的操作,
interface Network{
public void browser();
}
class Real implements Network{
public void browser(){
System.out.println("上网浏览信息");
}
}
class Proxy implements Network{
private Network network;
public Proxy(Network network){
this.network = network;
}
public void check(){
System.out.println("检查用户是否合法。");
}
public void browser(){
this.check();
this.network.browser(); // 调用真实的主题操作
}
}
public class ProxyDemo{
public static void main(String args[]){
Network nw = new Proxy(new Real); // 设置代理操作
nw.browser(); // 客户只关心一个上网操作
}
}
5、适配器设计
适配器设计在图形界面上用的非常多。
对于一个Java程序,如果一个类要实现一个接口,必须覆写接口里的全部抽象方法, 但是有一些抽象方法可能在类里并没有用到,这样全部实现其实会增加许多工作量,因此需要一个中间过渡类,但是此过渡类又不希望被直接使用,所以将过渡类定为抽象类比较合适,即一个接口首先被一个抽象类(也叫适配器类)继承,并在此抽象类中实现若干抽象方法,以后的子类直接继承此抽象类,就可以有选择的覆写所需要的抽象方法。
interface Window{ // 定义window接口,表示窗口操作
public void open(); // 打开
public void close(); // 关闭
public void activated(); // 窗口活动
public void iconified(); // 窗口最小化
public void deiconified(); // 恢复窗口大小
}
abstract class WindowAdapter implements Window{
public void open(){}; // 打开
public void close(){}; // 关闭
public void activated(){}; // 窗口活动
public void iconified(){}; // 窗口最小化
public void deiconified(){}; // 恢复窗口大小
}
class WindowImp extends WindowAdapter{
public void open(){
System.out.println("窗口打开")
}
public void close(){
System.out.println("窗口关闭")
}
}
public class WindowAdapterDemo{
public static void main(String args[]){
Window window = new WindowImp();
window.open();
window.close();
}
}
6、总结
重要:
在开发中,一个类永远不要去继承一个已经实现的类,要么实现接口,要么继承抽象类,如果接口和抽象类同时可以使用,优先使用接口,避免单继承局限。