本章目标
掌握抽象类及接口的实例化操作
掌握模板设计的作用
掌握工厂设计模式的作用
掌握代理设计模式的作用
掌握适配器设计模式的作用
掌握抽象类与接口的使用区别
为抽象类与接口实例化
在Java中可以通过对象的多态性,为抽象类和接口实例化,这样再使用抽象类和接口的时候就可以调用本子类中所覆写过的方法了。
为抽象类实例化
abstract class A{//定义抽象类 A
public abstract void print();//定义抽象方法 print()
}
class B extends A{//子类继承抽象类
public void print(){
System.out.println("Hello World!!!");
}
}
public class AbstractCaseDemo01 {
public static void main(String[] args) {
A a = new B();//通过子类为抽象类实例化
a.print();//调用的方法是被子类覆写过的方法
}
/*结果:
* Hello World!!!
* */
}
为接口实例化
interface A{//定义接口 A
public abstract void print();//定义抽象方法 print()
}
class B implements A{//子类实现接口
public void print(){
System.out.println("Hello World!!!");
}
}
public class InterfaceCaseDemo01 {
public static void main(String[] args) {
A a = new B();//通过子类为接口实例化
a.print();//调用的方法是被子类覆写过的方法
}
/*结果:
* Hello World!!!
* */
}
抽象类的实际应用 —— 模板设计
来看下面的这样一种场景:“假设人分为学生和工人,学生和工人都可以说话,但是学生和工人说话的内容是不一样的,也就是说说话这个功能应该是一个具体功能,而说话的内容就要由学生或工人来决定了”,所以此时就可以使用抽象类实现这种场景
抽象类的实际应用
abstract class Person{//定义抽象类 Person
private String name;//定义 name 属性
private int age;//定义 age 属性
public Person(String name, int age){//为属性初始化
this.name = name;//为 name 属性赋值
this.age = age;//为 age 属性赋值
}
public String getName(){//取得 name 属性内容
return name;
}
public int getAge(){//取得 age 属性内容
return age;
}
public void say(){//说话是具体功能,要定义成普通方法
System.out.println(this.getContent());//说话的内容由子类决定
}
public abstract String getContent();
}
class Student extends Person{//定义 Student 类继承 Person 类
private float score;
public Student(String name, int age ,float score){//调用父类的构造方法
super(name , age);
this.score = score;
}
public String getContent(){//覆写父类中的抽象方法
return "学生信息 --> 姓名:"+super.getName()+"; 年龄:"
+super.getAge()+";成绩:"+this.score;
}
}
class Worker extends Person{//定义 Worker 类继承 Person 类
private float salary;
public Worker(String name, int age, float salary){//调用父类的构造方法
super(name ,age);
this.salary = salary;
}
public String getContent(){//覆写父类中的抽象方法
return "工人信息 --> 姓名:"+super.getName()+"; 年龄:"
+super.getAge()+";工资:"+this.salary;
}
}
public class AbstractCaseDemo02 {
public static void main(String[] args) {
Person per1 = null;//声明 Person 对象
Person per2 = null;//声明 Person 对象
per1 = new Student("张三", 30, 99.0f);//学生是一个人
per2 = new Worker("李四", 30, 3000.0f);//工人是一个人
per1.say();//学生说学生的内容
per2.say();//工人说工人的内容
}
/*结果:
* 学生信息 --> 姓名:张三; 年龄:30;成绩:99.0
* 工人信息 --> 姓名:李四; 年龄:30;工资:3000.0
* */
}
提示:现实生活中的模板
对于以上的操作代码,如果读者不是很理解的话,那么可以看一下以下的说明,小的时候有些读者因为淘气可能会填写过如下的登记表:
接口的实际应用 —— 制定标准
接口在实际中更多的作用是用来制订标准的。比如说:“U盘和打印机都可以插在电脑上使用,这是因为它们都实现了USB的接口,对于电脑来说,只要是符合了USB接口标准的设备就都可以插进来
制订USB标准
interface USB{//定义 USB 接口
public void start();//USB 设备开始工作
public void stop();//USB 设备结束工作
}
class Computer{
public static void plugin(USB usb){//只要是 USB 的设备就都可以插入
usb.start();//让 USB 设备开始工作
System.out.println("========= USB 设备工作 =========");
usb.stop();//让 USB 设备停止工作
}
}
class Flash implements USB{//U盘
public void start(){//覆写 start() 方法
System.out.println("U盘开始工作。");
}
public void stop(){//覆写 stop() 方法
System.out.println("U盘停止工作。");
}
}
class Print implements USB{//打印机
public void start(){//覆写 start() 方法
System.out.println("打印机开始工作。");
}
public void stop(){//覆写 stop() 方法
System.out.println("打印机停止工作。");
}
}
public class InterfaceCaseDemo02 {
public static void main(String[] args) {
Computer.plugin(new Flash());//插入 U 盘
Computer.plugin(new Print());//插入打印机
}
/*结果:
* U盘开始工作。
* ========= USB 设备工作 =========
* U盘停止工作。
* 打印机开始工作。
* ========= USB 设备工作 =========
* 打印机停止工作。
* */
}
设计模式 —— 工厂设计
工厂设计,是Java开发中使用的最多的一种设计模式,那么什么叫工厂设计,以及工厂设计有那些作用呢?在说明问题前,请读者先观察以下的程序。
观察程序中的问题
interface Fruit{//定义一个水果的接口
public void eat();//吃水果的方法
}
class Apple implements Fruit{//定义子类 Apple
public void eat(){//覆写 eat() 方法
System.out.println("** 吃苹果。");
}
}
class Orange implements Fruit{//定义子类 Orange
public void eat(){//覆写 eat() 方法
System.out.println("** 吃橘子。");
}
}
public class InterfaceCaseDemo03 {
public static void main(String[] args) {
Fruit f = new Apple();//实例化接口
f.eat();//调用方法
}
/*结果:
* ** 吃苹果。
* */
}
问题的解决
工厂设计模式
interface Fruit{//定义一个水果的接口
public void eat();//吃水果的方法
}
class Apple implements Fruit{//定义子类 Apple
public void eat(){//覆写 eat() 方法
System.out.println("** 吃苹果。");
}
}
class Orange implements Fruit{//定义子类 Orange
public void eat(){//覆写 eat() 方法
System.out.println("** 吃橘子。");
}
}
class Factory{//定义工厂类
public static Fruit getInstance(String className){//定义接口对象
Fruit f = null;
if("apple".equals(className)){//判断是哪个子类的标记
f=new Apple();//通过 Apple 实例化接口
}
if("orange".equals(className)){//判断是哪个子类的标记
f=new Orange();//通过 Orange 实例化接口
}
return f;
}
}
public class InterfaceCaseDemo04 {
public static void main(String[] args) {
Fruit f = null;//定义接口对象
f = Factory.getInstance("apple");//通过工厂取得实例
f.eat();//调用方法
}
/*结果:
* ** 吃苹果。
* */
}
工厂类的操作流程
设计模式 —— 代理设计
代理设计也是在java开发中使用较多的一种设计模式,所谓的代理设计就是指一个代理主题来操作真实主题,真实主题执行具体的业务操作,而代理主题负责其他相关业务的处理,就好比在生活中经常使用到的代理上网那样,客户通过网络代理连接网络,由代理服务器完成用户权限,访问限制等与上网操作相关的操作。
分析结果
不管是代理操作也好,真实的操作也好,其共同的目的就是一个上网,所以用户关心的只是如何上网,至于里面是如何操作的用户并不关心
代理操作
interface Network{ // 定义Network接口
public void browse() ; // 定义浏览的抽象方法
}
class Real implements Network{ // 真实的上网操作
public void browse(){ // 覆写抽象方法
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 browse(){
this.check() ; // 可以同时调用多个与具体业务相关的操作
this.network.browse() ; // 调用真实上网操作
}
}
public class ProxyDemo{
public static void main(String args[]){
Network net = null;//定义接口对象
net = new Proxy(new Real());//实例化代理,同时传入代理的真实操作
net.browse();//客户只关心上网浏览一个功能
}
/*结果:
* 检查用户是否合法
* 上网浏览信息
* */
}
代理操作流程
设计模式 —— 适配器设计
对于Java程序来说,如果一个类要实现一个接口,则肯定要覆写此接口中的全部抽象方法,那么如果,此时一个接口中定义的抽象方法过多,但是在子类中又用不到这么多抽象方法的话,则肯定很麻烦,所以此时就需要一个中间的过渡,但是此过渡类又不希望被直接使用,所以将此过渡类定义成抽象类最合适,即一个接口首先被一个抽象类(此抽象类通常称为适配器类),并在此抽象类中实现若干方法(方法体为空),则以后的子类直接继承此抽象类,就可以有选择的覆写所需要的方法。
适配器设计实现
interface Window{//定义 Window 接口,表示窗口操作
public void open();//窗口打开
public void close();//窗口关闭
public void activated();//窗口活动
public void iconified();//窗口最小化
public void deiconfifed();//窗口恢复大小
}
//定义抽象类实现接口,在此类中覆写方法,但所有的方法体为空
abstract class WindowAdapter implements Window{
public void open(){};//覆写 open() ,方法体为空
public void close(){};//覆写 close() ,方法体为空
public void activated(){};//覆写 activated() ,方法体为空
public void iconified(){};//覆写 iconified() ,方法体为空
public void deiconfifed(){};//覆写 deiconfifed() ,方法体为空
}
//子类直接继承 WindowAdapter 类,有选择地实现需要的方法
class WindowImpl extends WindowAdapter{
public void open(){//真正实现 open() 方法
System.out.println("窗口打开。");
}
public void close(){//真正实现 close() 方法
System.out.println("窗口关闭。");
}
}
public class AdapterDemo{
public static void main(String args[]){
Window win = new WindowImpl();//实现接口对象
win.open();//调用 open() 方法
win.close();//调用 close() 方法
}
/*结果:
* 窗口打开。
* 窗口关闭。
* */
}
内部类的扩展
在之前面向对象的基础部分,曾经为读者讲解过内部类的概念,实际上在一个抽象类中也可以定义多个接口或抽象类,在一个接口中也可以定义多个抽象类或接口。
在一个抽象类中包含接口
abstract class A{//定义抽象 A
public abstract void printA();//定义抽象方法
interface B{//定义内部接口
public void printB();//定义抽象方法
}
}
class X extends A{//继承抽象类
public void printA(){//实现抽象方法
System.out.println("HELLO --> A");
}
class Y implements B{//定义内部类实现内部接口
public void printB(){//实现内部接口的抽象方法
System.out.println("HELLO --> B");
}
}
}
public class InnerExtDemo01{
public static void main(String args[]){
A.B b =new X().new Y();//实例化内部接口对象
b.printB();//调用内部接口的抽象方法
}
/*结果:
* HELLO --> B
* */
}
在一个接口中包含抽象类
interface A{//定义接口 A
public abstract void printA();//定义抽象方法
abstract class B{//定义内部抽象类
public abstract void printB();//定义抽象方法
}
}
class X implements A{
public void printA(){//实现接口的抽象方法
System.out.println("HELLO --> A");
}
class Y extends B{//在接口实现类中定义内部类
public void printB(){//实现内部抽象类的抽象方法
System.out.println("HELLO --> B");
}
}
}
public class InnerExtDemo02{
public static void main(String args[]){
A.B b =new X().new Y();//实例化内部接口对象
b.printB();//调用内部抽象类的方法
}
/*结果:
* HELLO --> B
* */
}
抽象类与接口之间的关系