接口:
开发原则:接口优先原则,在一个场景既可以使用抽象类也可以使用接口的时候,优先考虑使用接口.
定义:接口中只有全局常量和抽象方法(JDK8之前),接口使用interface定义接口.
2.使用原则:
a.接口无法直接创建实例化对象,需要通过具体子类向上转型为其实例化。
b.接口命名一般以I 开头,子类实现一般以implements关键字实现接口,一般以impl结尾,表示此类是一个接口的子类。(接口名+impl)
c.接口允许多实现(多继承),一个子类可以同时使用implements实现若干接口。
注:真正new的子类才有意义,不要被前边的类名称或接口名称搞晕。
通过共同子类建立的关系。
例子:
interface IMessage{
//全局常量,final为常量,static为全局变量
public static final String MSG = "BIT";
//抽象方法
public abstract void getMsg();
}
interface INews{
public abstract void getNews();
}
//此时MessageImpl同时是INews与IMessage的子类
class MessageImpl implements IMessage,INews{
public void getMsg(){
System.out.println(MSG);
}
public void getNews(){
System.out.println(MSG);
}
}
public class Test{
public static void main(String[] args) {
IMessage msg = new MessageImpl() ;
msg.getMsg();
//INews news = new MessageImpl();
//父接口间的相互转换。
INews news = (INews) msg;
news.getNews();
}
}
运行结果:
d.接口中只允许public权限,即便不写也是public.接口中abstract,final,static均可省略不写.(强制要求不写)
阿里编码规约:接口中的方法和属性不要加任何修饰符号,public也不要加,保持代码的简洁性.
e.当子类既需要继承抽象类又需要实现接口时,先extends一个抽象类而后使用implements实现多个接口.(继承单继承,未知写后边)
例子:
interface IMessage{
//全局常量,final为常量,static为全局变量
public static final String MSG = "BIT";
//抽象方法
public abstract void getMsg();
}
abstract class News{
public abstract void getNews();
}
class MessageImpl extends News implements IMessage{
public void getMsg(){
System.out.println(MSG);
}
public void getNews(){
System.out.println(MSG);
}
}
public class Test{
public static void main(String[] args) {
IMessage msg = new MessageImpl() ;
msg.getMsg();
//News news = new MessageImpl();
//IMessage与News有共同的子类
News news = (News) msg;
news.getNews();
}
}
运行结果:
f.接口和抽象类的关系
抽象类可以使用implements实现多个接口,接口不能继承抽象类(抽象类是普通类的超集),接口可以使用extends继承多个父接口.
例子:
interface A{
//抽象方法,有返回值声明
void A();
}
interface B{
//抽象方法
void B();
}
interface C extends A,B{
void C();
}
class D implements C{
public void A(){ }
public void B(){ }
public void C(){ }
}
public class Test{
public static void main(String[] args) {
C c = new D();
c.C();
}
}
3.接口应用场景: 混合
- 定义操作标准(USB接口、Type-c接口 、5G标准)
- 表示一种能力、行为
例子:
//定义标准
interface USB{
//安装驱动
void setUp();
//正常工作
void work();
}
class Mouse implements USB{
public void setUp(){
System.out.println("安装鼠标驱动。。");
}
public void work(){
System.out.println("鼠标正常工作");
}
}
class Keyboard implements USB{
public void setUp(){
System.out.println("安装键盘驱动。。");
}
public void work(){
System.out.println("键盘正常工作");
}
}
class Computer{
public void plugin(USB usb){
usb.setUp();
usb.work();
}
}
public class Test{
public static void main(String[] args) {
Computer computer = new Computer();
computer.plugin(new Mouse());
computer.plugin(new Keyboard());
}
}
结果:
23种设计模式–软件工程
代码重构:扩展功能(在基础代码之上增加功能)
《HeadFirst设计模式》
五大设计原则:
OCP原则(开闭原则)
定义:一个软件实体如类,接口等应该对扩展开放,修改关闭.
所有设计模式先找第三方(找到此设计模式,共同的父类)。
第三方:模板类,将核心算法与具体子类相分离,子类只需要覆写具体的某几步流程即可.
模板设计模式(模板方法):
- 基于抽象类的设计模式
定义:在一个方法中定义一个算法的骨架(如冲泡饮料流程),而将一些步骤延迟到子类中实现
- 优点:模板模式可以使得子类在不改变核心算法的基础上,具体实现算法中的某些步骤
举例:星巴克冲咖啡,泡茶
重复代码一次都不准出现
1.(核心):为了不让子类修改,将核心配置封装在父类中 -->将方法使用final封装。
- 代码:冲咖啡,泡茶
- 问题:咖啡与茶在制作过程中,烧水与倒入杯中的两个过程重复操作,
- 想法:将这两个方法提取出放在父类(基类)中,让咖啡与茶都继承此父类.
class CaffeineBeverage{
public void boilWater(){}
public void pourInCup(){}
}
例子:
abstract class CaffeineBeverage {
//核心算法,子类只能使用。
public final void prepareRecipe() {
boilWater();
//抽象方法,在父类中不知道子类要什么饮料
brewBeverage();
//抽象方法,同上
pourInCup();
addCondiments();
}
public void boilWater() {
System.out.println("将水烧开");
}
public void pourInCup() {
System.out.println("将饮料倒入杯中");
}
public abstract void brewBeverage();
public abstract void addCondiments();
}
class Coffee extends CaffeineBeverage{
public void brewBeverage(){
System.out.println("冲泡咖啡");
}
public void addCondiments(){
System.out.println("加糖和牛奶");
}
}
class Tea extends CaffeineBeverage{
public void brewBeverage(){
System.out.println("浸泡茶包");
}
public void addCondiments(){
System.out.println("加柠檬");
}
}
public class Test{
public static void main(String[] args) {
CaffeineBeverage coffee = new Coffee();
System.out.println("给大佬泡咖啡");
coffee.prepareRecipe();
System.out.println("---------");
CaffeineBeverage tea = new Tea();
System.out.println("给大佬递茶");
tea.prepareRecipe();
}
}
- 我们来看此时的类图;
模板类的组成:
类比于实验模板,简历模板
- final修饰的核心算法
- Abstract修饰的抽象方法,延迟子类实现
- 普通具体方法,所有子类都一样,子类直接使用即可
- 钩子方法 hook()
–默认不做事的方法,子类可以视情况而定,是否需要覆写.
钩子方法的使用:
import java.util.Scanner;
abstract class CaffeineBeverage {
//核心算法,子类只能使用。
public final void prepareRecipe() {
boilWater();
//抽象方法,在父类中不知道子类要什么饮料
brewBeverage();
//抽象方法,同上
pourInCup();
if(isCustomerWantsCondiments()){
addCondiments();
}
}
public void boilWater() {
System.out.println("将水烧开");
}
public void pourInCup() {
System.out.println("将饮料倒入杯中");
}
public abstract void brewBeverage();
public abstract void addCondiments();
//钩子方法,默认所有饮料均需要加调料
public boolean isCustomerWantsCondiments(){
return true;
}
}
class Coffee extends CaffeineBeverage{
public void brewBeverage(){
System.out.println("冲泡咖啡");
}
public void addCondiments(){
System.out.println("加糖和牛奶");
}
}
class Tea extends CaffeineBeverage{
public void brewBeverage(){
System.out.println("浸泡茶包");
}
public void addCondiments(){
System.out.println("加柠檬");
}
public boolean isCustomerWantsCoundiments(){
System.out.println("您需要加柠檬吗?y表示需要");
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
if(str.equals("y")){
System.out.println("客户想要柠檬");
return true;
}else{
System.out.println("客户喜欢原味");
return false;
}
}
}
public class Test{
public static void main(String[] args) {
CaffeineBeverage coffee = new Coffee();
System.out.println("给大佬泡咖啡");
coffee.prepareRecipe();
System.out.println("---------");
CaffeineBeverage tea = new Tea();
System.out.println("给大佬递茶");
tea.prepareRecipe();
}
}
运行结果:
工厂设计模式(重点)
Java基础要求掌握三种实际模式:
- 工厂
- 代理
- 单例
第三方:工厂类,将客户端的产生对象与具体子类分离,提取(解耦)到专门的工厂类中产生对象.
a.简单工厂模式
1.没有工厂类时,用户无法便捷灵活的得到想要的产品.
- 问题本质:主方法(客户端)直接与具体产品交互.
- 解决方法:将客户端产生商品的行为(new 对象)提取到一个新的类中–>工厂类
**
特点:
- 一个抽象产品类(接口,如:computer)
- 多个具体的产品类(如:Macbookpro)
- 一个工厂(负责生产所有具体商品,客户端与工厂交互,不与具体产品交互)
当多个具体产品呈现出家族式特征时(如微软系,苹果系),
为了保证不同产品系之间的隐私性,不同产品系有自己的工厂。
b.工厂方法模式
- 当产品出现家族式特征时
特点:
- 一个抽象产品类(接口,如Computer)
- 多个具体的产品类(如MacbookPro)
- 一个抽象工厂
- 多个具体工厂(如微软工厂,苹果工厂)
代理设计模式
—类比代练或代购
- 真实业务类
- 辅助类
代理模式:
第三方:代理类,将真实业务与辅助操作解耦(买电脑与出国排队,发快递解耦).
特点:一个接口,两个子类,其中一个子类负责完成真实业务,
另一个子类辅助之
代理类中:
1.需要传入真实业务对象,代理类需要知道真实客户是谁,完成真实业务是由真实对象来完成,代理只需要辅助之,通过构造方法传入。
2.传入的是接口对象:只要是接口中定义的业务,代理都可以进行代理.(只要是买电脑,代购都可以处理,若传入真实类,则只能代购具体品牌电脑)