四、单一职责原则与接口分离原则

单一职责原则 (Simple Responsibility Pinciple,SRP)

这个原则其实很有意思,他规定每个类所拥有的能力必须明确划分,吃饭就吃饭,洗澡就洗澡,睡觉就睡觉,这保证了每个类的相互的能力不会互相污染,你不能一个吃饭的类居然可以出来洗澡的方法,这听起来就很荒谬。

如果你在学习的时候乐于查看源码,不难会有这样疑问:为什么我们看起来明明可以一步完成的操作他要写那么多封装类还有那么深的层次结构来完成,这很难理解。这也是源码学习晦涩难懂的一部分的原因。

但是,我还是那句话,如果站在更高层次来思考这个问题,不难发现设计者的良苦用心,职责分的细彼此之间相互耦合的可能性就小,功能也就方便维护,不过这个请适可而止,也并不是说吃饭功能你需要细节到吃哪一粒米,这没有必要,不必要的借口太多反而不好维护。你只要在怎么吃这个功能上细分就好。

今天呢,我还是去吃饭,不过饭店推出了简约套餐豪华套餐

简约套餐:做得很快,但是菜品很简单,很适合早餐,让我们在短时间内就可以完成吃饭动作。

豪华套餐:做得比简约套餐慢许多,但是菜品很丰富,很适合聚餐,晚餐这种有较多时间等待和享用的类型。
老样子,最简单的初版。对套餐(Set)进行编写。

public class Set{
    public void eat(String type){
        if("简约套餐".equals(type)){
            // print 选择简约套餐
        }else{
            // print 选择豪华套餐
        }
    }
}
public static void main(String[] ars){
    Set set = new Set();
    set.eat("简约套餐");
    set.eat("豪华套餐");
}

当然,写成这样还是老问题,就是开闭原则之类的问题。

不过有一点我想要说明的是,设计原则最多也还是参考作用,我们应该尽量遵守,因为真正的业务可能会让我们不得不打破一些看起来很美好的原则,所以比起强制套用设计原则,不如学会善用他们来解决让你挠头的业务问题。

回归正传,这个时候,饭店认为推出的简约套餐豪华套餐 销量不错,但是顾客觉得花样太单一了,于是为了回应顾客新的业务需求,我们就需要修改一下当初的设计,乘着还没有酿成大祸之前。

public class SimpleSet{
    public void eat(String type){
        System.out.println(type+": 简单快捷.");
    }
}
public class DiffSet{
    public void eat(String type){
        System.out.println(type+": 奢华大气.");
    }
}

我们将两种套餐分成了两个类,为了把他们的职责细分,不再像是以前全部的职责都放在了Food类中,避免了污染。

public static void main(String[] ars){
    DiffSet dset = new Diffset();
    dset.eat("奢华套餐");
    SimpleSet sset = new SimpleSet();
    sset.eat("简约套餐");
}

但这样感觉还是不够好,因为之前依赖倒置中讲过:高层模块与底层模块应该依赖抽象这一概念,所以我们使用接口来再次设计一下。

public interface ISet{
    void eat(String type);
}
public SimpleSetImpl implements ISet{
    //和之前一样
}
public DiffSetImpl implements ISet{
    //和之前一样
}
public static void main(String[] ars){
    ISet dset = new DiffsetImpl();
    dset.eat("奢华套餐");
    ISet sset = new SimpleSetImpl();
    sset.eat("简约套餐");
}

再回到我们新的需求的问题,我们可以有三种选择。

第一种,我们可以继承简约套餐,而重写里面eat方法。

public SimpleSetImplA extends SimpleSetImpl{
    @Override
    public void eat(String type){
        System.out.println(type+": A套餐");//简约的A套餐
    }
}
public SimpleSetImplB extends SimpleSetImpl{
    @Override
    public void eat(String type){
        System.out.println(type+": B套餐");//简约的B套餐
    }
}

第二种,我们所使用的SimpleSetImpl不应该使用,而应该使用抽象类,让所继承他的子类自由实现自己的套餐内容。也是我比较推荐的一种。

public abstract class DefaultSimpleSet implements ISet{
    //------------
    //*********** 以上是关于套餐的默认方法,表示一些固定的价钱和适用人群到底初始化
    public abstract void eat(String type);
    //让简单套餐的子类去具体实现吃的方法,继承的子类将会自动成为简约套餐的子项。
}
public SimpleSetImplA extends DefaultSimpleSet{
    @Override
    public void eat(String type){
        System.out.println(type+": A套餐");//简约的A套餐
    }
}
public SimpleSetImplB extends DefaultSimpleSet{
    @Override
    public void eat(String type){
        System.out.println(type+": B套餐");//简约的B套餐
    }
}

第三种,设计两个接口,一个是ISimpleSet,一个是IDiffSet接口,实现方法我直接贴出来。

public interface ISimpleSet{
    void eat(String type);
}
public interface IDiffSet{
    void eat(String type);
}

//这里只实现简约套餐
public class SimpleSetImpA implements ISimpleSet{
    //具体实现 A 套餐的 eat
}
public class SimpleSetImpB implements ISimpleSet{
    //具体实现 B 套餐的 eat
}

当然我想到了第四种。正好可以提前预热以下接口隔离原则

public interface ISimpleSet implements ISet{
    // eat 方法
    void simpleSetMethod();//简约套餐独有的方法
}
public interface IDiffSet implements ISet{
    // eat 方法
    void DiffSetMethod();//奢华套餐独有的方法
}

后面就和第三种方法一样。

总结一下单一职责,其实就是对功能的细分,并且要对将来的会发展成什么样子做出比较良好的架构,对面接口,这将会对你的拓展有很大帮助。

接口隔离原则 (Interface Segregation Principle, ISP)

是指用多个专门的接口,而不使用单一的总接口,客户端不应该依赖它不需要的接口。这个原则指导我们在设计接口时应当注意一下几点:
1、一个类对一类的依赖应该建立在最小的接口之上。
2、建立单一接口,不要建立庞大臃肿的接口。
3、尽量细化接口,接口中的方法尽量少(不是越少越好,一定要适度)。

代码我是我从别的地方粘贴过来的,这个大概的内容我其实在上面的四种方法一样,类应该只要依赖一个或者更少的接口。
并且每个都应该有明确的功能,用来区别接口的作用。

这里我就不再赘述了。

版权声明:本文为CSDN博主「PopCandier」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/CandyCCCation/article/details/88899480

你可能感兴趣的:(四、单一职责原则与接口分离原则)