里氏代换原则在Java以及设计模式中的体现

​里氏代换原则在Java中的体现

 

前面说了里氏代换原则,那么现在说一下里氏代换原则在Java中的使用。

 

里氏代换原则要求父类类型可以使用的,那么子类一定可以适用。因此子类必须具有基类的全部接口,并且可能更广。如果Java程序破坏了这个条件,那么编译器就会出错。

 

这里以接口为例:在接口中规定了所有的方法都必须是public,这其实就是一种对里氏代换原则的体现,因为接口被其它类所实现,那么接口就是父类,这个父类的类型如果不是public,那么就无法被其它子类调用,就违反了前面说的父类类型可以使用的,子类一定可以适用的规则。

 

另外如果一个父类接口Base声明了一个public方法,那么子类B是不能够将这个方法的访问权限public修改为低级的private,因为如果子类B将权限设置为private那么这个方法只能被自己的类调用,而无法被其它类调用,这样就违反了里氏代换原则。

 

public interface Base {
    //默认public
    public void method();
}


public class Son implements Base {
    @Override
    private void method() {

    }
}

 

编译器会报如下错误!

 

 

里氏代换原则在设计模式中的体现。

 

策略模式

 

其实说到里氏代换原则首先就会想到策略模式,因为策略模式的核心就是封装到基类中的一种实现方式。

 

前面我也在了解业务时学习了一些策略模式,策略模式讲的是,如果有一组算法,那么就将每一个算法封装起来,使得它们可以互相交换。

 

 

 

 

上图中可以看到在实现策略模式时,不同的策略类的具体实现都会实现共同的接口,这个接口是为了保证所有的策略类的相关角色都会在接口中确定,这样就保证了所有的角色都在同一类型的结构中。

 

接口中变量的真实类型则是具体的策略类。即会在接口中返回具体的类型,这个类型就是需要实现的策略类。

/**
 * 基类类型
 */
public interface Base {
    //默认public
    public Object toDo(int type);
}



/**
 * 策略的具体实现类
 */
public class StrategyA implements Base{

    @Override
    public Object toDo(int type) {
        System.out.println("策略A的实现");
        return type;
    }
}




/**
 * 策略的具体实现类
 */
public class StrategyB implements Base {
    @Override
    public Object toDo(int type) {
        System.out.println("策略B的实现");
        return type;
    }
}



/**
 * 策略的具体实现类
 */
public class StrategyC implements Base {
    @Override
    public Object toDo(int type) {
        System.out.println("策略C的实现");
        return type;
    }
}



/**
 * 该类返回具体的策略
 */
public class Context {
    private Base base;

    /**
     * 初始化类型,所有的策略都实现了基类Base,即参数中传递哪个策略类型就返回哪个策略类型
     * @param base
     */
    public Context(Base base){
        this.base = base;
    }


    /**
     * 执行策略
     * @param type
     * @return
     */
    public Object excute(int type){
        return base.toDo(type);
    }

}



public class ExtendsDemo {
    public static void main(String[] args) {
        //初始化对应的策略,然后调用策略就可以得到对应策略的实现
        Context context = new Context(new StrategyA());
        //此时执行的就是策略A
        context.excute(1);

        //执行策略B
        Context context1 = new Context(new StrategyB());
        context1.excute(2);


        //执行策略C
        Context context2 = new Context(new StrategyC());
        context2.excute(3);

    }
}

 

 

 

代理模式

 

代理模式的核心就是给一个类提供一个代理类,然后去做想做的事情,更简单话理解就是类似于房产中介,我想买房但是自己不想看各种问题,就找房产中介,中介就是代理类。

 

 

代理模式在Java中给一个对象提供代理对象,并由代理对象控制原对象的引用。因此代理对象可以获得原对象的所有权做原对象可以做的事情。

 

 

 

 

从上图中可以看到原对象已经与基类建立了引用关系,现在存在一个代理类代理原对象,那么这个代理类也与基类建立了引用关系,因此代理类也和基类进行了关系绑定。

 

/**
 * 基类类型
 */
public interface Base {
    //默认public
    public Object toDo(int type);
}


/**
 * 原对象与基类建立引用
 */
public class Agent implements Base {
    @Override
    public Object toDo(int type) {
        System.out.println("原对象");
        return null;
    }
}



/**
 * 代理类
 */
public class AgentProxy implements InvocationHandler {

    private Object object;

    public AgentProxy(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理开始");
        Object res = method.invoke(object,args);
        System.out.println("代理结束返回结果");
        return res;
    }
}


public class AgentMain {
    public static void main(String[] args) {
        Base base = new Agent();

        Base proxy = (Base) Proxy.newProxyInstance(
            Base.class.getClassLoader(),
            new Class[]{Base.class},
            new AgentProxy(base));

        proxy.toDo(1);
    }
}

 

 

 

 

 

 

 

参考资料:

 

1、《Java与模式》

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值