欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

设计模式(一)设计原则

程序员文章站 2022-03-14 10:14:24
...

设计模式(一)设计原则

开闭原则

定义:一个软件实体,如类、模块、函数应该对扩展开放,对修改关闭。例如面向抽象编程,而不要面向实现编程。

优点:提高软件系统的可复用性、可维护性。

依赖倒置原则

定义:高层不应该依赖底层模块,二者都应该依赖抽象。要针对接口编程,不要针对实现编程。

优点:减少类的耦合性,提高稳定性、代码可读性、可维护性。

依赖倒置原则和开闭原则举例:

MyBatis在使用Mapper的时候

SqlSession sqlSession = sqlSessionFactory.openSession();

会调用DefaultSqlSessionFactory的openSessionFromDataSource方法。

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {final Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);}

其中Configuration.newExecutor方法。

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    if (ExecutorType.BATCH == executorType) {
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
      executor = new SimpleExecutor(this, transaction);
    }
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);
    }
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }

Configuration持有的引用是Executor接口,而Executor接口有3个实现类:

设计模式(一)设计原则

BaseExecutor抽象类使用模板方法模式,定义了通用的方法实现。供ReuseExecutor、SimpleExecutor、BatchExecutor调用。
SimpleExecutor是最简单的Executor接口实现,ReuseExecutor和SimpleExecutor的区别是:ReuseExecutor能重用Statement。而BatchExecutor能够批量执行sql。
CachingExecutor使用了装饰模式,给Executor接口实现类封装了二级缓存的功能,稍后专写一篇关于它的介绍。

这里就遵循了依赖导致原则和开闭原则,Configuration持有的引用是Executor接口,依赖的是Executor接口,而非具体的实现类。同时对扩展开放,如果要增加新的Executor,只需要新增加一个XXXExecutor,并在初始化的时候new即可。

单一职责原则

定义:一个类、接口、方法应该只有一个职责。

现实编码中,很难严格遵守,基本上没有哪个类做到单一职责。建议方法级别做到单一职责原则。

优点:降低类的复杂度,提高类的可读性、可维护性。

单一职责举例:

在MyBatis的mapper文件中经常可以看到通用型的update方法:

public int update(Student student);

对应的xml文件往往是:

<update id="update">
    UPDATE student SET 
    name = #{name}, 
    age = #{age}, 
    gender = #{gender}, 
    phone = #{phone}, 
    class = #{class}, 
    type = #{type}, 
    update_by = #{updateBy.id}, 
    update_date = #{updateDate}, 
    remarks = #{remarks}
    WHERE id = #{id}
</update>

无论要修改Student的那个属性,所有属性都要修改一遍,如果要修改name,就要写一个单一职责的方法:

public int update(@Param("name") String name,@Param("id") String id);
<update id="update">
    UPDATE student SET 
    name = #{name}
    WHERE id = #{id}
</update>

迪米特法则

定义:又叫做最少知道原则。一个对象应该对其他对象保持最少的了解。

强调只和朋友交流,不和陌生人说话。

出现在成员变量、方法的输入输出参数中的类称为成员朋友类,而出现在方法体内部的类不属于朋友类。

优点:降低耦合度。

迪米特法则举例:

Java中有PO/Entity: persistent object持久对象、VO:view object表现层对象、DTO:data transfer object,数据传输对象、DAO :data access object数据访问对象、POJO :plain ordinary java object用这个名字用来强调它是一个普通java对象,而不是一个特殊的对象。

它们有时可以通用,各自有各自的生命周期作用范围。

设计模式(一)设计原则

设计模式(一)设计原则

在实际的开发中,经常可以看到Entity从持久层一直传送到Controller层,违反了迪米特法则,Controller、Service、Dao层每一层应该仅和自己的“朋友”打交道。

接口隔离原则

定义:client不应该依赖它不需要的接口。接口依赖遵循最少依赖原则。尽量细化接口。

优点:使得类具有好的可读性、可扩展性、可维护性。

里氏替换原则

定义:如果将程序中的对象A替换为对象B,程序的行为没有发生变化,那么B就是A的子类型。

所有引用父类的地方必须能够透明的使用其字类的对象,字类对象能够替换父类对象, 同时程序逻辑不变。

子类可以扩展父类的功能,但不能改变父类原有功能。

子类可以实现父类的abstract方法,但不能覆盖父类的非abstract方法。子类可以增加自己特有的方法。

子类重载父类的方法时,方法的入参要比父类的方法的入参更宽松。方法的出参要比父类的方法出参更严格或一样。

优点:提高程序健壮性。提高可维护性、扩展性。

相关标签: 设计模式