设计模式七大基本原则学习解析

软件设计原则

为了提高软件的可维护性和可复用性,增加软件的可扩展性和灵活性,要根据几个基本原则来开发软件

开闭原则

对扩展开放对修改关闭

  • 在程序需要被扩展的时候,不去修改原有的代码,而是实现一种热插拔的效果*

  • 就是要使用的时候插上就可以用,不用的时候就拔掉不使用

  • 要实现这样的效果需要使用到接口和抽象类

    • 就是在程序需要扩展的时候,不选择修改方法,而是重新创建一个实现类对象来扩展

例子

public abstract class AbstractSkin {
    //抽象皮肤接口
    public abstract void display();
}

//实现类
public class DaFaultSkin extends AbstractSkin{
    @Override
    public void display() {
        System.out.println("默认皮肤");
    }
}
public class NewSkin extends AbstractSkin{
    @Override
    public void display() {
        System.out.println("自定义皮肤");
    }
}

//调用的一个总的集合
public class Sougou输入法 {
    //这里是通过赋值的方式来将对应的实现类传入到该总类中
    private AbstractSkin skin;

    public Sougou输入法(AbstractSkin skin) {
        this.skin = skin;
    }

    public void display(){
        skin.display();
    }
}

//Main
public static void main(String[] args) {
        Sougou输入法 s = new Sougou输入法(new DaFaultSkin());
        //这个就是使用默认皮肤了
        s.display();

        new Sougou输入法(new NewSkin()).display();
        //这个就是使用自定义的皮肤了
    }

里氏代换原则

任何基类可以出现的地方,子类一定可以出现

  • 就是子类可以扩展父类的功能,但不能改变父类原有的功能
  • 就是子类继承父类时,尽量只是添加新的方法完成新功能,对旧有的父类方法尽量不去重写他

例子

正方形不是长方形

因为正方形是一种特殊的长方形,所以在定义正方形中,就可以让正方形去继承长方形的类

先来一个负面例子

public class changfangxing {
    //长方形类
    private double width;
    private double length;

    public double getWidth() {
        return width;
    }

    public void setWidth(double width) {
        this.width = width;
    }

    public double getLength() {
        return length;
    }

    public void setLength(double length) {
        this.length = length;
    }
}

//正方形类
public class zhengfangxing extends changfangxing{
     @Override
    public void setLength(double length){
         super.setLength(length);
         super.setWidth(length);
     }
    @Override
    public void setWidth(double length){
        super.setLength(length);
        super.setWidth(length);
    }

}

这里如果我对上面2个类都调用一个扩宽方法

public static void resize(changfangxing changfangxing){
        //如果宽如果比长小,就把它扩宽
        while(changfangxing.getLength()>=changfangxing.getWidth()){
            changfangxing.setWidth(changfangxing.getWidth()+1);
        }

    }

运行长方形没有问题,但是正方形就会进入死循环,因为正方形的长度设置是长宽一起增长的,所以方法进入死循环

  • 这样就不符合里氏代换原则了

在这里插入图片描述

  • 所以需要作出修改

改进

//定义的四边形的接口
public interface shibianxing {
    double getLength();
    double getWidth();
    //分别定义获取长和宽的方法
}

//正方形类
public class zhengfangxing implements shibianxing{

    private double side;
    public double getSide() {
        return side;
    }
    public void setSide(double side) {
        this.side = side;
    }
    @Override
    public double getLength() {
        return side;
    }
    @Override
    public double getWidth() {
        return side;
    }
}

//长方形类
public class changfangxing implements shibianxing{
    private double length;
    private double width;
    @Override
    public double getLength() {
        return this.length;
    }
    public void setLength(double length) {
        this.length = length;
    }
    public void setWidth(double width) {
        this.width = width;
    }
    @Override
    public double getWidth() {
        return this.width;
    }
}

使用这种方法来定义的长方形和正方形类就没有明确的父子关系,只有相同的源(四边形接口)

这样就无法使用对扩宽函数传递正方形对象了

依赖倒转原则

  • 高层模块不应该依赖低层模块,两者都应该依赖其抽象
    • 就是在需要A继承B的时候,不然A继承B,而是从B中抽取一个出一个接口,让A继承该接口
  • 抽象不应该依赖细节,细节应该依赖
    • 主要是面向抽象接口的编程,而不是面对实现类进行编程,来实现降低客户与实现模模块的耦合度

在这里插入图片描述

例子:组装电脑

  • 如果对于电脑的每一个配件(像是CPU,GPU,内存等)都独立创建一个类
  • 再将这些类放入一个大类(computer类)的话,如果要修改使用的配件的话,就要对整个电脑类进行修改,非常麻烦
  • 这样就违反了开闭原则

改进

  • 使用接口,让每一配件都实现对应的配件需要的接口
  • 这样computer类的扩展性就非常高了

单一职责原则

  • 单个接口或类不应该有多个职责,应该尽可能的划分职责,通过组合的方式,完成更为复杂的业务
    • 感觉这个和接口隔离原则差不多

作用

  1. 降低类的复杂度,一个类只负责一项职责。
  2. 提高类的可读性,可维护性
  3. 降低变更引起的风险

注意

  1. 通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码级违反单一职责原则;只有类中方法数量足够少,可以在方法级别保持单一职责原则

例子 : 学生工作安排例子

  • 学生工作分为生活辅导和学业辅导
  • 如果将这2个工作都交给同一人进行的话,有可能在生活辅导方面这个人做得不好要换人,但却因为这个人学业辅导做得很好换不了
  • 所以这2个工作分为2部分,分别交给辅导员和指导老师处理

接口隔离原则

  • 客户端不应该被迫依赖于它不使用的方法
    • 其中B类就是客户端

在这里插入图片描述

  • 一个类对另一个类的依赖应该建立在最小的接口上
    • 就是将A类对应的所有方法分别分割为几个小的接口
    • 客户端只要选自己需要的接口继承就可以

在这里插入图片描述

例子 : 安全门

  • 现在定义了一个安全门的接口,里面有防盗,防火,解锁功能
  • 如果我有一个安全门的品牌继承了这个接口,就一定要实现里面的所有功能
  • 如果我想要做的品牌是不生产带防火功能的安全门,那么就会被接口限制不得不去实现该功能
  • 这样就违反了接口隔离原则了

改进

  • 将对应的几个功能分割为3个接口
  • 让要生产的门分别继承接口即可
    • 这样就可以生产出可以只防盗,不能解锁和防火的门了

迪米特法则

  • 最少知识原则

    • 只和你的朋友交谈,不和’陌生人’交谈
    • 这里的朋友指的是 :当前对象本身,当前对象的成员对象,当前对象所创建的对象,当前对象的方法参数等
      • 这些对象同当前对象存在关联,聚合或组合关系,可以直接访问这些对象的方法
  • 如果2个软件实体无需直接通信的话,就不应该发生直接的相互调用,可以通过第三方去转发该调用

    • 这样可以降低类与类之间的耦合度,提高独立性

在这里插入图片描述

例子 : 明星和经纪人的关系

  • 对于一个明星,他会拥有粉丝和对应的合作公司
  • 明星肯定不可能直接和这些对象沟通
  • 所以需要使用一个中间对象(经纪人)来帮忙处理这些事务

主要还是为了降低明星和这几个类之间的耦合度

合成复用原则

  • 尽量先使用组合或聚合等关联关系来实现类的复用
    • 其次再考虑使用继承关系来实现

通常类的复用分为合成复用和继承复用

在这里插入图片描述

例子 : 汽车分类管理系统

在这里插入图片描述

  • 可以看到如果使用继承复用的话,会产生很多的子类
  • 每增加一种新的动力的汽车,就需要再重新定义新的类

改进

在这里插入图片描述

  • 在汽车类中聚合一个color(颜色)的接口
  • 这样在添加新动力的汽车的是时候只需要调用Car类中对应的color方法添加对应的颜色即可
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值