初窥设计模式之七大原则(上篇)

这是我参与更文挑战的第1天,活动详情查看:更文挑战

java语言的特性是封装、多态、继承,设计模式就是在此特性上诞生各种业务场景的解决方案

使用设计模式的目的是为了 让我们的软件有更好的

  1. 代码重用性(相同的代码不用多次编写)
  2. 可读性(编码规范性,便于其他程序员的阅读和理解)
  3. 可扩展性(方便增加新的功能)
  4. 可靠性(当我们增加新的功能后 对原来功能没有影响)
  5. 使程序呈现 高内聚,低耦合

设计模式在软件开发中的应用: 面向对象(oop)=>功能模块设计(设计模式+算法)=>框架(多种设计模式)=>架构(服务集群)

设计模式七大原则

  • 单一职责原则
  • 接口隔离原则
  • 依赖倒转原则
  • 里氏替换原则
  • 开闭原则
  • 迪米特原则
  • 合成复用原则

单一职责原则:

一个类应该只负责一项职责,但并不是只有一个方法

接口隔离原则:

客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上
如:实际生产中 接口之间依赖关系错综复杂 就会产生循环依赖问题

依赖倒转原则

  1. 高层模块不应该依赖底层模块,二者都应该依赖抽象
  2. 抽象不应该依赖细节,细节应该依赖抽象
  3. 依赖倒转的中心思想是面向接口编程

在java中抽象指的是 接口或抽象类,细节指的是具体的实现类

示例业务需求

给手机实现接收微信 接收邮件功能

反面案例:

定义邮件功能

class Email0{
    public String getInfo(){
        return "Email0: hello!";
    }
}
复制代码

定义微信功能

class Weixin0{
    public String getInfo(){
        return "Weixin0: hello!";
    }
}
复制代码

定义手机 实现接收邮件 接收微信的功能

class Phone{
    public void recieve(Email0 email0){
        System.out.println(email0.getInfo());
    }

    public void recieveWeixin(Weixin0 weixin0){
        System.out.println(weixin0.getInfo());
    }
}
复制代码

定义客户端使用手机

 public class DependenceInversion {

    public static void main(String[] args) {
        new Phone().recieve(new Email0());
        new Phone().recieveWeixin(new Weixin0());
    }
}
复制代码

以上这种写法也可以实现功能 但是代码看起来比较臃肿而且不容易维护。
假如现在增加 让手机可以接收短信的功能,则需要:

  1. 定义好短信功能
  2. 手机类实现接收短信功能
  3. 客户端使用手机调用接收短信方法

在第二步则违背了 依赖倒转原则 高层部分直接依赖了底层模块,细节依赖细节,复杂的业务逻辑没有抽象层支撑;

优化:
定义抽象层”接收信息”
各部分功能实现抽象层 编写对应的功能逻辑
手机功能依赖抽象层
客户端根据自己需求 定义手机实现对应功能

优化后代码

定义接口

interface Ireceiver{
    String getInfo();
}
复制代码

定义邮件功能 实现接口

class Email implements Ireceiver{
    @Override
    public String getInfo() {
        return "邮件服务:hello word";
    }
}
复制代码

定义微信功能 实现接口

class Weixin implements Ireceiver{
    @Override
    public String getInfo() {
        return "微信服务:hello weixin";
    }
}
复制代码

定义手机 依赖于抽象层

class Person{
    public void receive(Ireceiver ireceiver){
        System.out.println(ireceiver.getInfo());
    }
}
复制代码

定义客户端使用手机不同功能

public class DependenceInversion1 {
    public static void main(String[] args) {
        Person person=new Person();
        person.receive(new Email());
        person.receive(new Weixin());
    }
}
复制代码

依赖关系传递的三种方式:

示例业务需求:

存在播放器 player 需要使用接口类ITV 中的play方法

接口传递

ITV接口

interface ITV{
    public void play();
}
复制代码

player 接口

interface IPlayer{
    public void open(ITV itv);
}
复制代码

player 类

class Player implements IPlayer{
    @Override
    public void open(ITV itv) {
        itv.play();
    }
}
复制代码

构造方法传递

ITV接口

interface ITV2{
    public void play();
}
复制代码

player 接口

interface IPlayer2{
    public void open();
}
复制代码

player 类

class Player2 implements IPlayer2{

    public ITV2 tv;

    public Player2(ITV2 tv){
        this.tv=tv;
    }
    @Override
    public void open() {
        this.tv.play();
    }
}
复制代码

setter方式传递

ITV 接口

interface ITV3{
    void play();
}
复制代码

player 接口

interface Player3{
    void open();
}
复制代码

player 类

class Player3 implements IPlayer3{
    private ITV3 tv;

    public void setTv(ITV3 tv) {
        this.tv = tv;
    }

    @Override
    public void open() {
        this.tv.play();
    }
}
复制代码

依赖倒转细节

  • 低层模块尽量都要有抽象类或者接口,或者两者都有,程序稳定性更好。
  • 变量的声明类型尽量是抽象类或者接口,这样我们的变量引用和实际对象间就存在一个缓冲层,利于程序的扩展和优化。
  • 继承时遵循里氏替换原则。

时间原因暂时先写到这 里氏替换原则详见下一篇

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享