ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

面向对象六大设计原则和设计模式,持续更新中

2021-10-06 16:30:47  阅读:150  来源: 互联网

标签:六大 职责 对象 面向对象 实例 原型 单例 抽象 设计模式


设计原则与设计模式

六大设计原则

1、单一职责

​ 一个类只能有且仅有一个引起他变化的原因。即一个类只负责一件事。多继承违背了单一职责。

​ 如果一类或对象承担有过多职责,则一个职责的变换可能会削弱或抑制其他职责,耦合性高;当需要一个只负责一个职责的对象时,需要实现其所有职责,造成代码的冗余。

优点:
  • ​ 降低类的复杂度,类只负责一个职责,则逻辑比多职责简单。

  • ​ 提高代码可读性

  • ​ 提高系统的可维护性

  • ​ 降低软件变更的风险

    实现方法:

    将对象根据职责进行拆分:比如大学生的学生工作可分为生活工作和学习工作。根据这两个职责,可将学生工作的管理和指导对象拆分为两个对象。

2、开闭原则

​ 软件应对扩展开放,对修改关闭。

实现方法:

​ 通过抽象约束、封装变化来实现开闭原则,即通过接口或者抽象类为软件实体定义一个相对稳定的抽象层,将相同的可变因素封装在具体实现类中。尽可能的抽象合理。、

作用:

​ 提高代码的可复用性,提高软件的可维护性,方便扩展代码或功能的测试。

3、接口隔离原则

​ 客户端不应该被迫依赖于它不需要的方法。一个类对另一个类的依赖应建立在最小的接口上。需要对接口进行拆分。(单一职责是对对象或类进行拆分)即为各个类建立专门的接口而不是实现一个庞大的功能众多的接口。

接口隔离原则和单一职责的不同
  • 接口隔离主要约束接口,主要针对抽象和程序的整体框架;单一职责原则主要是约束类,针对的是程序中的实现和细节。

  • 接口个理原则注重的是类对接口的依赖隔离;单一职责注重的是类的职责

    优点:
  • 降低耦合性

  • 提高可维护性

  • 保证系统的稳定性

  • 体现对象的层次

  • 减少代码的冗余

    实现:

    ​ 学生管理系统包含插入成绩、删除成绩、修改成绩、计算总成绩、打印信息、查询成绩等等这些全部放到一个接口会造成程序的臃肿,可将其拆分为输入、统计、打印三个模块。

4、依赖倒置

​ 高层模块不应依赖于底层模块,两者都应依赖于其抽象。抽象不应依赖于细节,细节依赖于抽象。核心为:面向接口编程。

​ 由于细节具有多变性,抽象相对稳定,因此以抽象为基础搭建出的结构比细节为基础搭建的架构要稳定的多。抽象指的是:抽象类或接口,细节指的是实现类。

作用:
  • 降低类间耦合性

  • 提高系统的稳定性

  • 提高代码的可读性和可维护性

  • 减少并发风险

    实现:
  • 每个类尽量提供接口或抽象类,或两者都具备

  • 变量的声明尽量是接口或者抽象类

  • 任何类不应从具体类派生

  • 继承时尽量遵循里氏替换原则

    例如:顾客购物:如果不对商店进行抽象,则顾客每次从不同商店购买东西,则需要写不同的实现代码。而如果对商店进行抽象,则只需在传参时设置商店即可。

5、里氏替换

保证继承时超类的所有性质在子类中仍然成立,是对开闭原则的补充。其定义:

  • 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
  • 子类可以增加自己的方法。
  • 子类重载父类的方法时,方法的传参要比父类的更宽松
  • 子类实现父类的方法时,方法的输出或返回要比父类更加严格或相等。
作用:
  • 里氏替换原则是实现开闭原则的重要方法之一
  • 克服了子类重写父类造成可复用性变差的缺点。
  • 降低代码出错的可能
  • 加强了程序的健壮性
实现方法

​ 关于里氏替换原则的例子,最有名的是“正方形不是长方形”。当然,生活中也有很多类似的例子,例如,企鹅、鸵鸟和几维鸟从生物学的角度来划分,它们属于鸟类;但从类的继承关系来看,由于它们不能继承“鸟”会飞的功能,所以它们不能定义成“鸟”的子类。同样,由于“气球鱼”不会游泳,所以不能定义成“鱼”的子类;“玩具炮”炸不了敌人,所以不能定义成“炮”的子类等。

例如“几维鸟不是鸟”

迪米特法则

​ 最少知识原则:一个对象尽可能对其他对象尽可能少的了解。对象之间的耦合性降到最低。类与类的关系越密切,耦合性就越高。

​ 如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。

优点:
  • 降低类之间的耦合性,提高模块之间的相对独立性。
  • 提高类的可复用率和系统的可扩展性。
实现:

强调以下两点:

  • 从依赖者的角度说,只依赖应该依赖的对象。
  • 从被依赖者的角度说,只暴露应该暴露的方法。

实现时注意:

  • 创建类时,应创建弱耦合的类
  • 类的结构设计应尽量降低类成员的访问权限。
  • 类的设计上,优先将类设置为一个不可变类。
  • 对其它的类的引用次数降到最低。
  • 不暴露类的属性成员,提供相应的访问器(get和set方法)
  • 谨慎使用序列化功能。

例如明星与经纪人的关系示例。明星的日常事务由经纪人处理,明星不直接和媒体公司和粉丝进行交涉。

设计模式:

单例模式:

定义:

​ 一个类只能有一个实例,且该类能够自行创建这个实例。

特点:
  • 单例类只有一个实例对象。
  • 该单例必须由单例类自行创建。
  • 单例类对外提供一个访问该单例的全局访问节点。
优缺点:
优点:
  • 保证内存中有且仅有一个实例,减少内存的开销。
  • 一个实例可以避免对资源的过多占用。
  • 设置全局访问点,可以优化和共享资源的访问。
缺点:
  • 没有接口扩展困难,如果要扩展则需要改动原代码
  • 单例模式不利于调试,在调试过程中,如果单例中的代码没有执行完,也不能模拟生成一个新的对象。
  • 单例模式可能违背单一职责。
应用场景:
  • 需要频繁创建的一些类,使用单例可以降低系统的内存压力,减少 GC。
  • 某类只要求生成一个对象的时候,如一个班中的班长、每个人的身份证号等。
  • 某些类创建实例时占用资源较多,或实例化耗时较长,且经常使用。
  • 某类需要频繁实例化,而创建的对象又频繁被销毁的时候,如多线程的线程池、网络连接池等。
  • 频繁访问数据库或文件的对象。
  • 对于一些控制硬件级别的操作,或者从系统上来讲应当是单一控制逻辑的操作,如果有多个实例,则系统会完全乱套。
  • 当对象需要被共享的场合。由于单例模式只允许创建一个对象,共享该对象可以节省内存,并加快对象访问速度。如 Web 中的配置对象、数据库的连接池等。
实现:

​ 将类的构造设为私有,外部类就无法调用类的构造函数,也就无法生成多个实例。类自身定义一个静态私有实例,并向外提供一个静态的公有函数用于创建或获取该静态私有实例。

懒汉模式:
public class LazySingleton{
    private static volatile LazySingleton instance = null;
    
    private LazySingleton(){
    }
    
    public static synchronized LazySingleton getInstance(){
        if(instance == null){
            instance = new LazySingleton();
        }
        return instance;
    }
}
饿汉模式:
public class HungrySingleton{
    private static final HungrySingleton instance = new HungrySingleton();
    
    private HungrySingleton(){
    }
    
    public static HungrySingleton getInstance(){
        return instance;
    }
}

原型模式:

定义:

​ 用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或者相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无需知道创建对象的具体细节。

优缺点:
优点:

​ Java自带的原型模式基于二进制流的复制,在性能上比直接new一个新对象更加优良。

​ 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建的过程,以便在需要的时 候使用(如恢复),可辅助实现撤销操作。

缺点:
  • 需要为每一个类配置一个clone方法。
  • clone方法位于类的内部,当对已有类进行改造时需要修改代码,违背了开闭原则。
  • 当实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层的对象都必须支持深克隆,实现起来很麻烦。因此深克隆和浅克隆需要使用得当。
实现:

​ 原型模式主要包括3个主要角色:

  1. 抽象原型类:具体原型对象必须实现的接口Cloneable
  2. 具体原型类:实现原型类的clone方法,它是可被复制的方法。
  3. 访问类:使用具体原型类中的clone方法来复制新的对象
//具体原型类
class Realizetype implements Cloneable {
    Realizetype() {
        System.out.println("具体原型创建成功!");
    }
    public Object clone() throws CloneNotSupportedException {
        System.out.println("具体原型复制成功!");
        return (Realizetype) super.clone();
    }
}
//原型模式的测试类
public class PrototypeTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        Realizetype obj1 = new Realizetype();
        Realizetype obj2 = (Realizetype) obj1.clone();
        System.out.println("obj1==obj2?" + (obj1 == obj2));
    }
}

标签:六大,职责,对象,面向对象,实例,原型,单例,抽象,设计模式
来源: https://blog.csdn.net/qq_45728449/article/details/120626063

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有