1.复用

继承和组合的区别

  • 继承的关系是“is-a”关系,例如汽车和交通工具的关系;
  • 组合的关系是“has-a”关系,例如汽车和轮胎的关系;
  • 一般来说组合能够实现继承的功能,达到复用功能的效果,但是使用继承会导致子类过分依赖于父类,因此父类的改动会导致代码维护困难。尽量使用组合来替代继承关系。

protected和private区别

  • protected允许子类访问该方法,例如使用super来访问父类中的方法;
  • private则只允许本类内的访问,子类等也不能访问private修饰的方法;

构造函数其实是隐式的static方法,构造函数不具有多态性

2.接口

抽象类和抽象方法abstract

  • 抽象类无法用于构造对象,只是作为各个子类的基类来用;
  • 包含抽象方法的类叫做抽象类,如果一个类包含了一个或者多个类,该类必须被限定为抽象类,否则报编译错误;

接口interface

  • interface提供了一个完全抽象类,类中没有任何的实现。(在抽象类中可以有部分的方法实现);
  • interface替代class来声明一个接口;
  • 在接口中的域是默认static和final的;
  • 接口是可以互相嵌套的;

java的默认访问修饰符是public

协变类型是指在继承关系中,重写方法的返回类型可以与父类不同;

适配器模式

  • 应用场景:当另一个类希望复用现有类的功能,但是这两个类之间不存在太大的关系(继承关系);

  • 使用方法:通过引入一个适配器来使用现在的类,将一个类的接口转换成用户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

  • 接下来我用一个实例来对类的适配器模式进行更深一步的介绍。
    a. 实例概况
    背景:小成买了一个进口的电视机
    冲突:进口电视机要求电压(110V)与国内插头标准输出电压(220V)不兼容
    解决方案:设置一个适配器将插头输出的220V转变成110V
    即适配器模式中的类的适配器模式
    b. 使用步骤
    步骤1: 创建Target接口(期待得到的插头):能输出110V(将220V转换成110V)

    1. public interface Target {
    2. //将220V转换输出110V(原有插头(Adaptee)没有的)
    3. public void Convert_110v();
    4. }


步骤2: 创建源类(原有的插头) ;

  1. class PowerPort220V{
  2. //原有插头只能输出220V
  3. public void Output_220v(){
  4. }
  5. }


步骤3:创建适配器类(Adapter)

class Adapter220V extends PowerPort220V implements Target{
   //期待的插头要求调用Convert_110v(),但原有插头没有
    //因此适配器补充上这个方法名
    //但实际上Convert_110v()只是调用原有插头的Output_220v()方法的内容
    //所以适配器只是将Output_220v()作了一层封装,封装成Target可以调用的Convert_110v()而已
@Override
public void Convert_110v(){
  this.Output_220v;
}


步骤4:定义具体使用目标类,并通过Adapter类调用所需要的方法从而实现目标(不需要通过原有插头)

//进口机器类
class ImportedMachine {
    @Override
    public void Work() {
        System.out.println("进口机器正常运行");
}
//通过Adapter类从而调用所需要的方法
public class AdapterPattern {
    public static void main(String[] args){

        Target mAdapter220V = new Adapter220V();
        ImportedMachine mImportedMachine = new ImportedMachine();

        //用户拿着进口机器插上适配器(调用Convert_110v()方法)
        //再将适配器插上原有插头(Convert_110v()方法内部调用Output_220v()方法输出220V)
        //适配器只是个外壳,对外提供110V,但本质还是220V进行供电
        mAdapter220V.Convert_110v();
        mImportedMachine.Work();
    }
}

策略模式

  • 应用场景:

    • 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
    • 2、一个系统需要动态地在几种算法中选择一种。
    • 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
  • 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。

  • 使用方法:

  • // 创建一个Context类,根据策略的不同,选择不同的操作;
    public class Context {
     private Strategy strategy;
    
     public Context(Strategy strategy){
        this.strategy = strategy;
     }
    
     public int executeStrategy(int num1, int num2){
        return strategy.doOperation(num1, num2);    //可以是sub、mul、add中的一种operation
     }
    }
    

工厂模式

  • 定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

  • 使用方式:例如建立一个ShapeFactory作为形状工厂,由用户来决定要构造哪种形状,再根据对象调用不同的draw()方法 ```java public class ShapeFactory { //使用 getShape 方法获取形状类型的对象 public Shape getShape(String shapeType){

    if(shapeType == null){
       return null;
    }        
    if(shapeType.equalsIgnoreCase("CIRCLE")){
       return new Circle();
    } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
       return new Rectangle();
    } else if(shapeType.equalsIgnoreCase("SQUARE")){
       return new Square();
    }
    return null;
    

    } }

public class FactoryPatternDemo { public static void main(String[] args) { ShapeFactory shapeFactory = new ShapeFactory(); //获取 Circle 的对象,并调用它的 draw 方法 Shape shape1 = shapeFactory.getShape(“CIRCLE”); //调用 Circle 的 draw 方法 shape1.draw(); //获取 Rectangle 的对象,并调用它的 draw 方法 Shape shape2 = shapeFactory.getShape(“RECTANGLE”); //调用 Rectangle 的 draw 方法 shape2.draw(); } } ```