天天看点

[Thinking in Java] - No.1 组合、继承和代理

什么是复用代码呢?当我们在项目程序中出现大量的重复或者结构极其相似的代码是,重复的工作会使得程序显得冗长,不易于管理,同时也浪费大量的时间空间资源。代码复用很好地解决了我们上面遇到的问题。除了常见的组合和继承方法,在这篇文章中我们还会介绍代理这种方法。

1. 组合:

什么是组合呢?简单来说就是has-a的关系。当我们需要使用到之前某个类的方法时,我们不需要重新实现该方法,只需要在新的类中引入原有类,然后通过对应的对象访问该方法即可。

/**
 * Created by YanMing on 2017/3/4.
 */
public class Claw {
    private int length;
    private int weight;

    public void eatUseClaw(){
        System.out.println("Eating with claw");
    }
}
           
/**
 * Created by YanMing on 2017/3/4.
 */
public class Cat {

    private Claw claw;

    public void catEat(){
        this.claw.eatUseClaw();
    }
}
           

2. 继承:

继承是我们Java语言和很多的OOP语言都不可缺少的部分。在Java中,在我们创建一个新的类的时候,我们总是需要指明我们继承自哪个基类,否则我们就是在隐式地从Java标准根累继承自Object。下面的例子你肯定不陌生:

/**
 * Created by YanMing on 2017/3/4.
 */
public class Shape {
    public Shape(){
        System.out.println("Shapppppppe");
    }
}
           
/**
 * Created by YanMing on 2017/3/4.
 */
public class Circle extends Shape{
    private double radius;

    public Circle(){
        System.out.println("Cirrrcle");
    }

    public static void  main(String args[]){
        Circle c = new Circle();

    }
}
           
[Thinking in Java] - No.1 组合、继承和代理

关于继承其他的只是都是比较基础的,这里不再赘述。我们主要是为了引入下面的代理方式。

3.代理:

Java并没有直接地对代理提供支持。这是一种继承和组合结合的方式,因为首先我们需要像组合一样,将一个成员对象置于所要构造的类中。但是同时,我们还在这个类中暴露了该成员对象的所有方法。例如:

/**
 * Created by YanMing on 2017/3/4.
 */
public class SpaceShipControls {
    void up(int velocity){}
    void down(int velocity){}
    void left(int velocity){}
    void right(int velocity){}
    void forward(int velocity){}
    void back(int velocity){}
    void turboBoost(){}
}
           
/**
 * Created by YanMing on 2017/3/4.
 */
public class SpaceShipDelegation {
    private String name;
    private  SpaceShipControls controls =
            new SpaceShipControls();
    public SpaceShipDelegation(String name){
        this.name = name;
    }
    public void up(int velocity)
    {
        controls.up(velocity);
    }
    public void down(int velocity)
    {
        controls.down(velocity);
    }
    public void left(int velocity)
    {
        controls.left(velocity);
    }
    public void right(int velocity)
    {
        controls.right(velocity);
    }
    public void forward(int velocity)
    {
        controls.forward(velocity);
    }
    public void back(int velocity)
    {
        controls.back(velocity);
    }
    public void turboBoost()
    {
        controls.turboBoost();
    }
}
           

我们来思考SpaceShipControls和SpaceShip之间的关系是什么?我们应该用继承么?SpaceShip显然,不能“is-a”SpaceShipControls,那么我们应该用组合么?这里用组合也可以。想想一下我们如果想要飞船前进怎么办?需要使用spaceship.controls.forward(xxx)。代理让我们可以在接触这个类的同时实现想要的业务逻辑。