1.抽象类的定义与使用
定义:抽象类只是比普通类多了一些抽象方法而已
抽象方法:只声明而未实现的方法(没有方法体),抽象方法必须使用abcstract关键字来定义。并且抽象方法所在的类也一定要使用abstract来定义 public abstract void
1.1 抽象类的是使用原则
a.所有抽象类必须有子类(final与abstract不能同时出现)
b.抽象类的子类必须覆写抽象类的所有抽象方法
c.抽象类无法直接创建实例化对象,需要通过子类向上转型为实例化
abstract class Person{
private String name;
public String getName(){
return name;
}
public abstract void test();
}
class student extends Person{
public void test(){
System.out.println("子类覆写抽象方法");
}
}
public class Test{
public static void main(String[] args){
Person per = new student();
per.fun();
}
}
1.2 抽象类相关约定
1.2.1 抽象类一定存在构造方法,子类也一定遵循对象实例化流程。先调用父类构造再调用子类构造
1.2.2 抽象类可以没有任何抽象方法,但此时仍然不能直接创建实例化对象
1.2.3 final与abstract不能同时出现
private与abstract也不能同时出现
1.2.4 关于内部抽象类:子类只需要覆写外部抽象类的直接抽象方法即可。内部抽象类的方法可不覆写。
2.模板设计模式
开闭原则(OCP):一个软件实体如类、模块或函数应该对扩展开放,对修改关闭。
模板(模板方法)设计模式:基于抽象类
在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板模式可以使得子类在不改变算法的前提下,重新定义算法中的某些步骤。
abstract class CaffeineBeverage {
final void prepareRecipe() {
boilWater();
子类实现:
brew();
pourInCup();
// 如果顾客想要饮料我们才调用加料方法
if (customerWantsCondiments()){
addCondiments();
}
}
abstract void brew();
abstract void addCondiments();
void boilWater() {
System.out.println("Boiling water");
}
void pourInCup() {
System.out.println("Pouring into cup");
}
boolean customerWantsCondiments() {
return true;
}
}
class Tea extends CaffeineBeverage {
void brew() {
System.out.println("Steeping the tea");
}
void addCondiments() {
System.out.println("Adding Lemon");
}
}
class Coffee extends CaffeineBeverage {
void brew() {
System.out.println("Dripping Coffee through filter");
}
void addCondiments() {
System.out.println("Adding Sugar and Milk");
}
public boolean customerWantsCondiments() {
String answer = getUserInput();
if (answer.equals("y")) {
return true;
}else {
return false;
}
}
private String getUserInput() {
String answer = null;
System.out.println("您想要在咖啡中加入牛奶或糖吗 (y/n)?");
Scanner scanner = new Scanner(System.in);
answer = scanner.nextLine();
return answer;
}
}
public class Test {
public static void main(String[] args) {
CaffeineBeverage tea = new Tea();
CaffeineBeverage coffee = new Coffee();
System.out.println("\nMaking tea...");
tea.prepareRecipe();
System.out.println("\nMaking Coffee");
coffee.prepareRecipe();
}
}
钩子方法(可以被覆写的方法)
3.接口的定义以及使用
接口优先原则:在一个操作既可以使用抽象类又可以使用接口的时候,优先考虑使用接口。
3.1 接口定义(JDK8以前)
接口就是抽象方法与全局常量的集合(纯粹版的抽象类),interface关键字定义接口
interfa IMyInterface{
//全局变量
public static final String MSG = "test";
//抽象方法
public abstract void test();
}
接口命名:接口使用I开头
子类要想使用接口,implements实现接口,一个子类可以同时实现多个接口(避免单继承局限)
子类命名规范:接口名为IMyInterFace,子类实现此接口命名为MyInterfaceImpl
父接口间的相互转换:前提是两个父接口拥有共同的实现子类
3.2 口使用限制
3.2.1 接口中只允许public权限(不管是常量还是方法,都是public权限,即便不写权限修饰符也是public)
阿里编码规约:接口中不要出现任何修饰符号,public也不要加
3.2.2
当子类既需要实现接口又需要继承抽象类时,请先使用extends继承一个抽象类,而后使用implements实现多个接口
3.2.3
一个抽象类可以使用implements实现多个接口,接口不能继承抽象类
class MessageImpl extends News implements IMessage
3.2.4
接口可以使用extends继承多个父接口(接口多继承)
3.3 接口应用
a.定义操作标准
b.表示能力
c.(了解)分布式开发中暴露远程服务方法
4.工厂设计模式
将客户端的new操作解耦到第三方(工厂类)
4.1 简单工厂-产品个数少且没有家族
a.一个抽象产品类(接口)- Computer
b.多个具体产品类 - MacbookPro、SurfaceBook
c.一个工厂(new 操作在此工厂中进行)- 客户端通过工厂类获取具体实例
4.2 工厂方法模式(横向扩展方便)-每个产品有自己家族,家族下有很多兄弟
定义一个用来创建对象的接口,让子类决定实例化哪一个类
针对每个产品(产品族)提供一个工厂类,客户端需要判断使用哪个工厂
a.一个抽象产品类
b.多个具体产品类
c.一个抽象工厂(-针对抽象产品类)
d.多个具体工厂(每个产品家族拥有自己的工厂)
4.3 抽象工厂模式(了解)-多个产品线混合