Java接口/内部类

抽象方法

我先举个例子引出抽象方法,例如求圆、矩形、三角形、这些图形的面积

🐤发现的问题

  • 每一个图形计算面积的方式都不一样, 所以每一个类都必须得要覆盖父类当中的getArea方法, 来去实现不同图形求面积的方式

🐸带来的问题

  • 怎么样保证子类必须得要覆盖父类当中定义的方法
  • 父类不需要提供方法体

抽象方法

定义格式:在方法前面添加了一个关键字abstract

🐬抽象方法的特点

  1. 抽象方法是没有方法体的
  2. 抽象方法必须得要定义在抽象类 或 接口当中
  3. 抽象方法不能是私有的privatefinal, static

🐤注意点

  • 子类必须得要去覆盖此方法(定义的抽象方法)
  • 在定义的时候不要有方法体

抽象类

  • abstract修饰的类,就成为了抽象类
  • 抽象类必须得要有子类才行。(抽象类一般都当作父类来继承)

🐥注意点

  • 抽象类是不能直接创建对象的
  • 抽象类当中,可以有抽象方法 ,也可以有非抽象方法(普通方法:给子类调用的)
  • 子类没有去覆盖抽象方法,会把子类也变成抽象类
  • 构造方法不能定义为私有化(抽象方法必须得要让子类继承之后,才能实现内部的方法体。子类继承的话,先去调用父类的构造方法)
  • 抽象类不能使用final来去修饰

🦄抽象类与普通的类的区别

  • 普通类你有的(方法 ,字段,构造器),抽象类都有
  • 抽象类不能创建对象。抽象类可以包含抽象方法,也可以包含非抽象方法
  • 抽象类必须有子类才有意义

接口

先来讲讲生活当中的物理接口

  • 指的是两个硬件设备之间的连接方式。硬件接口既包括物理上的接口,比如我们所以说的USB接口

🦄Java当中的接口

  • 在Java中,接口表示一种规范/约束/要求实现者必须遵循该规范,用来约束使用者应该怎么做

🐬规范和实现相分离的好处

主板上提供了USB插槽,只要一个遵循了USB规范的鼠标,就可以插入USB插槽,并与主板正常通信。至于这个鼠标是谁生产的,内部是如何实现的,主板都不需要关心(只要遵循了USB规范就可以插在主板上使用)。当鼠标坏了的时候,我主板不会坏

Java定义接口

  • Java接口也是表示一种规范,使用抽象方法来去定义一组功能
  • 实现者必须要给提供的方法实现

接口定义格式

interface 接口名称 {
   
}

🐤注意点

  • 接口是没有构造器,接口是不能创建对象的
  • 接口当中定义变量,都是全局的静态常量
  • 接口当中 定义的方法 都是公共的抽象方法
  • 接口是可以继承,它是可多继承:interface 接口名称 extends 继承的接口名, 继承的接口名

接口实现

实现格式

类名 extends 其它的类(只能继承一个类) implements 其它的接口(接口可以实现多个)

爬行动物规范

public interface Iwalkable {
    void walk();
}

水生动物规范

public interface Iswimable {
    void swim();
}

两栖动物规范

public interface Iamphibiousable extends Iwalkable, Iswimable {
}

动物类

public class Animal {
    String name;
    String Color;
}

狗类

public class Dog extends Animal implements Iwalkable {
    @Override
    public void walk() {
        System.out.println("小狗跑");
    }

    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "wc";
        dog.Color = "黑色";

        dog.walk();
    }
}

🐤接口与抽象类的区别

相同点

  • 都是被其它类继承和实现用的
  • 都不能实例化,都不能创建对象
  • 都可以定义抽象方法 ,定义的抽象方法子类都必须得要覆盖

不同点

  • 接口是没有构造器,抽象类当中是有构造器
  • 抽象类可以包含普通方法和抽象方法,接口当中只能有抽象方法,不能有普通方法(带有方法体)
  • 接口当中默认成员变量,要有初始值 都是静态的
  • 方法
    • 接口:当中方法默认public abstract 方法名;
    • 抽象类:默认的权限(default)

面向接口编程

  • 把实现类对象赋值给接口类型的变量,也就是多态
  • 多态的好处:屏蔽了不同类之间实现差异,从而达到通用编程

🐤接口多态

  • 把实现类赋值给接口 运行时, 运行的仍是实现类

USB规范

public interface IUSB {
    void swapData();
}

主板类,主要实现了USB的规范就可以和主板传输数据

class MotherBoard {
    void pluginIn(IUSB iusb) {
        iusb.swapData();
    }
}

键盘类,实现了USB规范

class keyBoard implements IUSB {

    @Override
    public void swapData() {
        System.out.println("键盘打字");
    }
}

鼠标类,实现了USB规范

class Mouse implements IUSB {

    @Override
    public void swapData() {
        System.out.println("鼠标移动");
    }
}
class Demo{
    public static void main(String[] args) {
        IUSB mouse = new Mouse();
        IUSB keyBoard = new keyBoard();

        MotherBoard board = new MotherBoard();
        board.pluginIn(mouse);
        board.pluginIn(keyBoard);
    }
}

内部类

  • 定义在类当中 的一个类
  • 内部类可以直接访问外部类当中 的成员

🐤为什么要有内部类

  • 增强封装,把内部类隐藏在外部类当中,不允许其它类访问这个内部类
  • 增加了代码的一个维护性

内部类分类

实例内部类

  • 直接定义在类当中的一个类,在类前面没有任何一个修饰符,不属于类的,不使用static修饰的类
public class Outter {
    String name = "BNTang";

    class Innner {
        void show() {
            System.out.println(name);
        }
    }
}

实例内部类的创建,想要使用实例内部类,必须得要先创建外部类

class Demo {
    public static void main(String[] args) {
        Outter outter = new Outter();
        Outter.Innner innner = outter.new Innner();
        innner.show();
    }
}

🐤实例内部类注意点

  • 想要使用实例内部类,必须得要先创建外部类
  • 在内部类当中可以访问外部类当中的成员
  • 在内部类当中,不能有静态(以static修饰的)的成员
  • 外部类是不能直接访问内部当中 的成员(代码块区域就不同当然不能访问)

实例内部类变量的访问

静态内部类

在内部类前面加上static,属于类的内部类

public class Outter {
    static String name = "BNTang";

    static class Innner {
        void show() {
            System.out.println(name);
        }
    }
}

🦄静态内部类的创建

class Demo {
    public static void main(String[] args) {
        Outter.Innner innner = new Outter.Innner();
        innner.show();
    }
}

静态内部类注意点

  • 静态内部类是不需要创建外部对象的
  • 在静态内部类当中,是没有外部类引用
  • 静态内部类,是可以访问外部类的静态成员
  • 静态内部类当中可以定义静态成员,也可以定义非静态成员

静态内部类当中访问外部的普通变量

匿名内部类

就是一个没有名字的局部内部类,只使用一次的时候,来去使用匿名内部类,匿名内部类必须得要有父类才可以, 或者是实现了接口,当然这个可以使用Java8中的Lambda表达式来优化,Java8我后面在写具体的文章来介绍

结构

new 父类的构造器 或 接口(){
  内部写的代码(在new时候就会自动执行)
}
public interface IUSB {
    void swapData();
}
class MotherBoard {
    void pluginIn(IUSB iusb) {
        iusb.swapData();
    }
}
class Demo{
    public static void main(String[] args) {
        MotherBoard board = new MotherBoard();
        board.pluginIn(new IUSB() {
            @Override
            public void swapData() {
                System.out.println("键盘打字");
            }
        });
        board.pluginIn(new IUSB() {
            @Override
            public void swapData() {
                System.out.println("鼠标移动");
            }
        });
    }
}

枚举

引出枚举

  • 枚举:比如:季节(春,夏,秋,冬)
  • 星期:周一到周日
  • 性别:男女
  • 表示一个事件固定状态

定义枚举

[修饰符] enum 枚举的名称 {
  常量1,常量2,常量3,...
}
public enum Sex {
    MAN,
    FEMALE
}

Person.java

public class Person {
    Sex name;
}
public class Demo {
    public static void main(String[] args) {
        Person person = new Person();
        person.name = Sex.MAN;

        System.out.println(person.name);
    }
}

枚举创建源码分析

UML中接口实现画法

  • 线条样式选择第二个再加三角空心箭头就表示实现的关系

工厂设计模式

  • 工厂模式是为了解耦,就是class A 想调用 class B,那么A只是调用B的方法,而至于B的实例化,就交给工厂类
  • 工厂模式可以降低代码重复,如果创建对象B的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码,我们可以把这些创建对象B的代码放到工厂里统一管理,既减少了重复代码,也方便以后对B的创建过程的修改和维护
  • 因为工厂管理了对象的创建逻辑,使用者并不需要知道具体的创建过程,只管使用即可,减少了使用者因为创建逻辑导致的错误

简单工厂设计模式

定义一个接口

public interface Fruit {
    void show();
}

定义两个水果类

public class Apple implements Fruit {
    @Override
    public void show() {
        System.out.println("苹果");
    }
}
public class Pear implements Fruit {
    @Override
    public void show() {
        System.out.println("梨");
    }
}

创建工厂

public class FruitFactory {
    public Fruit createFruit(String type) {
        if (type.equals("apple")) {
            return new Apple();
        } else if (type.equals("pear")) {
            return new Pear();
        } else {
            return null;
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        FruitFactory fruitFactory = new FruitFactory();
        Apple apple = (Apple) fruitFactory.createFruit("apple");
        apple.show();
        Pear pear = (Pear) fruitFactory.createFruit("pear");
        pear.show();
    }
}

工厂方法设计模式

定义一个接口

public interface Fruit {
    void show();
}

定义两个水果类

public class Apple implements Fruit {
    @Override
    public void show() {
        System.out.println("苹果");
    }
}
public class Pear implements Fruit {
    @Override
    public void show() {
        System.out.println("梨");
    }
}

创建FruitFactory接口

public interface FruitFactory {
    Fruit createFruit();
}

用到什么类, 就写什么工厂

AppleFactory

public class AppleFactory implements FruitFactory{
    @Override
    public Fruit createFruit() {
        return new Apple();
    }
}

PearFactory

public class PearFactory implements FruitFactory{
    @Override
    public Fruit createFruit() {
        return new Pear();
    }
}

Demo.java

public class Demo {
    public static void main(String[] args) {
        AppleFactory appleFactory = new AppleFactory();
        PearFactory pearFactory = new PearFactory();
        Apple apple = (Apple) appleFactory.createFruit();
        apple.show();
        Pear pear = (Pear) pearFactory.createFruit();
        pear.show();
    }
}

抽象工厂设计模式

Cpu

public interface Cpu {
    void run();

    class Cpu600 implements Cpu {
        @Override
        public void run() {
            System.out.println("Cpu600---run");
        }
    }

    class Cpu800 implements Cpu {
        @Override
        public void run() {
            System.out.println("Cpu800----run");
        }
    }
}

Screen

public interface Screen {
    void size();

    class Screen5 implements Screen {
        @Override
        public void size() {
            System.out.println("Screen5----size");
        }
    }

    class Screen8 implements Screen {
        @Override
        public void size() {
            System.out.println("Screen8---size");
        }
    }
}

PhoneFactory

public interface PhoneFactory {
    Cpu getCpu();
    Screen getScreen();
}

HongMiFactory

public class HongMiFactory implements PhoneFactory{
    @Override
    public Cpu getCpu() {
        return new Cpu.Cpu800();
    }
    @Override
    public Screen getScreen() {
        return new Screen.Screen8();
    }
}

Demo.java

public class Demo {
    public static void main(String[] args) {
        HongMiFactory hongMiFactory = new HongMiFactory();
        Cpu cpu = hongMiFactory.getCpu();
        Screen screen = hongMiFactory.getScreen();

        cpu.run();
        screen.size();
    }
}

工厂设计模式的选择

  • 对于简单工厂和工厂方法来说,两者的使用方式实际上是一样的
  • 如果对于产品的分类和名称是确定的,数量是相对固定的,推荐使用简单工厂模式
  • 抽象工厂用来解决相对复杂的问题,适用于一系列、大批量的对象生产
posted @ 2020-08-22 17:02  BNTang  阅读(421)  评论(0编辑  收藏  举报