Java设计模式

本文详细介绍了软件设计模式的概念,包括其起源、学习原因,以及各类模式如单例、工厂方法、抽象工厂等的定义、应用场景和优缺点。同时涵盖了面向对象设计原则和常见的模式分类,展示了如何通过遵循这些原则和模式提高代码的可维护性和复用性。
摘要由CSDN通过智能技术生成

一、概念

一、背景

        20世纪90年代,由建筑领域引入软件设计中。

        1995年,艾瑞克·伽马(ErichGamma)、理査德·海尔姆 (Richard Helm)、拉尔夫·约翰森(Ralph Johnson)、约翰·威利斯迪斯(JohnVlissides)等 4 位作者合作出版了《设计模式:可复用面向对象软件的基础》 一书,在此书中收录了 23 个设计模式,这是设计模式领域里程碑的事件。

二、概念

        软件设计模式(Software Design Pattern)就是对以前的程序员在实际开发中遇到的问题,进行总结优化,这些总结优化出来的解决方案就是软件设计模式。

三、学习原因 

        1.就是对面向对象设计的应用,对面向对象设计原则的应用,对封装,继承,多态,类之间关系的应用。

        2.可以提高设计能力,有助于阅读源码,提升程序设计的可维护性,可复用性,可扩展性(可扩展性一般指在添加新功能时,使代码改动成本最低,且不影响之前功能)。

二、建模语言(Unified Modeling Language,UML)

        一个开发人员进行设计的语言,使用各种图形符号来表示各模块之间的关系 。

        类图(Class diagram)是显示了模型的静态结构,类、类 的内部结构以及它们与其他类的关系,不显示暂时性的信息。

一、类

        类是指具有相同属性、方法和关系的对象的抽象,它封装了数据和行为,是 面向对象程序设计(OOP)的基础,具有封装性、继承性和多态性等三大特性。

二、接口

        接口(Interface)是一种特殊的类,它具有类的结构但不可被实例化,只可以 被子类实现。它包含抽象操作,但不包含属性。

三、类之间关系

1.依赖关系

        在一个类的方法中使用到了另一个类,具有临时性(方法使用结束就不使用了),低耦合。用带箭头的虚线来表示。

2.关联关系

        把一个类当作另一个类的属性,分为单向关联,双向关联,自关联(单例模式)。用一个带箭头的实线表示。

3.聚合关系

        聚合关系是关联关系的一种,是强关联关系。成员对象是整体对象的一部分,但是 成员对象可以脱离整体对象而独立存在。例如,学校与老师的关系,学校包含老 师,但如果学校停办了,老师依然存在。用带空心菱形的实线来表示。

4.组合关系

        组合也是关联关系的一种,是一种更强烈的聚合关系。一旦整体对象不存在, 部分对象也将不存在,部分对象不能脱离整体对象而存在。例如,头和嘴的关系, 没有了头,嘴也就不存在了。用带实心菱形的实线来表示。

5.继承关系

      是父 类与子类之间的关系,是一种继承关系,是 is-a 的关系。用带空心三角箭头的实线来表示。  

6.实现关系

        类实现了接口,类中的操作实现了接口中所声明的所有的抽象操作。用带空心三角箭头的虚线来表示。

三、面向对象设计原则

1.单一职责

        一个类不要负责太多事情,否则类内部耦合度太高,不利于扩展。高内聚,低耦合。

2.开闭原则

        程序扩展功能时,不建议修改原来代码,建议扩展一个新的类来实现新功能。

3.里氏替换原则

        在使用继承关系时,在子类中重写父类方法,不要在重写后对子类运行结果产生影响,子类原来调用父类的方法,方法重写后,子类可能会调错,产生影响。

4.依赖倒置

        有多个同类型事物时,可以抽取一个共同抽象层,具体实现细节应依赖于抽象。

5.接口隔离

        根据功能设计接口,不要将所有功能设计到一个接口中,不用是想一些不必要的功能。

6.迪米特原则

        最少了解原则,一个类最好只与自己相关类产生依赖,尽量不使用与自己没有直接关系的类,只与直接朋友交谈,不与陌生人交谈。

7.组合/聚合复用原则

        在某些情况下,B类想用A类中的方法,一般使用继承。但现在不使用继承,可以用关联的方式,调用A类中的方法;还可以在B类中依赖A类,在B类的一个方法中使用A类的方法(觉得这个更好)。

总结:

        开闭原则:要求对扩展开放,对修改关闭

        里氏替换原则:不要破坏继承体系

        依赖倒置原则:要求面向接口编程

        单一职责原则:实现类职责要单一

        接口隔离原则:在设计接口的时候要精简单一

        迪米特法则:只与直接的朋友的通信

        合成复用原则:尽量使用聚合和组合的方式,而不是使用继承

遵循设计原则:就是为了让程序高内聚,低耦合

四、模式设计

        1. 单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局 访问点供外部获取该实例,其拓展是有限多例模式。

        2. 原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。

        3. 工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子 类决定生产什么产品。

        4. 抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个 子类可以生产一系列相关的产品。

        5. 建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然 后根据不同需要分别创建它们,最后构建成该复杂对象。

        6. 代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客 户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。

        7. 适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口, 使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

        8. 桥接(Bridge)模式:将抽象与实现分离,使它们可以独立变化。它是用组 合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

        9. 装饰(Decorator)模式:动态的给对象增加一些职责,即增加其额外的功能。

        10. 外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子 系统更加容易被访问。

        11. 享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。

        12. 组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象 和组合对象具有一致的访问性。

        13. 模板方法(TemplateMethod)模式:定义一个操作中的算法骨架,而将算 法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定 义该算法的某些特定步骤。

        14. 策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它 们可以相互替换,且算法的改变不会影响使用算法的客户。

        15. 命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任 和执行请求的责任分割开。

        16. 职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下 一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。

        17. 状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能力。

        18. 观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改 变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。

        19. 中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互 关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。

        20. 迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数 据,而不暴露聚合对象的内部表示。

        21. 访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个 元素提供多种访问方式,即每个元素有多个访问者对象访问。

        22. 备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对 象的内部状态,以便以后恢复它。

        23. 解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的 解释方法,即解释器。

五、模式分类

创建型模式:

        用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使 用分离”。提供了单例、原型、工厂方法、抽象工厂、建造者 5 种创建型模式。

结构型模式:

        用于描述如何将类或对象按某种布局组成更大的结构,提供了代理、 适配器、桥接、装饰、外观、享元、组合 7 种结构型模式。

行为型模式:

        用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独 完成的任务,以及怎样分配职责。提供了模板方法、策略、命令、职责链、状态、 观察者、中介者、迭代器、访问者、备忘录、解释器 11 种行为型模式。 

六、常用设计模式

1.单例模式:

        概念:        

        解决一个类在一个程序中保证只能创建一个类。(也是适用的方式)

例如:Windows任务管理器窗口,只需创建一个

        特点:

        只创建一个对象;对象由单例类自己创建;向外提供访问方法。

        实现:

        饿汉式:在类加载时就把唯一的对象创建好,且不存在线程安全问题。但启动系统时加载的东西很多。

        懒汉式:不是在类加载时,第一次获取单例对象时,创建对象。但存在线程安全问题,加锁可以解决此类问题。双重检索+volatile。

//懒汉模式
public class WindowDome {
    static volatile WindowDome windowDome;//volatile修饰成员变量对其操作时禁止指令重排序

    private WindowDome(){
        System.out.println("WindowDome");
    }
    /*
    有线程安全问题
    public WindowDome getWindowDome(){
        if (windowDome==null){
            windowDome = new WindowDome();
        }
        return windowDome;
    }
     */

    /*
    加锁是解决了线程安全问题,但并发情况效率低
     public synchronized WindowDome getWindowDome(){
        if (windowDome==null){
            windowDome = new WindowDome();
        }
        return windowDome;
    }
     */

  //用双重检索可解决高并发情况下线程安全问题
    public WindowDome getWindowDome(){
        if (windowDome==null){//第一波线程到来时全部进去,第二波到来时windowDome已经建立好了。
            synchronized(WindowDome.class){
                if (windowDome==null){//第一波第一个线程进来就创建,其余的都不符合条件就不创建对象了。
                    windowDome = new WindowDome();
                }
            }
        }
        return windowDome;
    }
}

Runtime 类属于典型的单例设计,利用 Runtime 类可以启动新的进 程或进行相关运行时环境的操作。比如,取得内存空间以及释放垃圾空间。

2.工厂模式:

2.1简单工厂模式

        简单工厂模式并不是 23 种设计模式之一,因为它违背了开闭原则,添加一个产品就需要修改一个工厂代码。

         概念:

        有一个工厂类负责生产某一类产品,同一产品具备同一个抽象父类(抽象类,接口),将创建的对象与使用的对象分离(spring框架就是这种设计)。

        该模式中包含的角色及其职责:

        工厂角色:负责实现创建所有实例的内部逻辑。工厂类提供静态方法,可以被外界直接调用,创建所需的产品对象。

        抽象产品角色:描述所有实例共有的接口。

        具体产品角色:创建目标。

        优点:

        实现了创建和调用的分离,降低了客户端代码的难度。 工厂类专门负责对象的创建;客户端只负责对象的调用。

        缺点:

        违反了开闭原则,不利于后期维护。增加和减少产品类,需要修改工厂类;如果产品类过多,就会导致工厂类过于庞大。

2.2工厂方法模式
        概念:

        对工厂进行抽象,一个抽象产品对应一个抽象工厂,一个具体产品对那个一个具体工厂。需要扩张新产品时,只需要添加新具体产品类和生产该产品的具体工厂类。就不必修改原来的工厂。

符合开闭原则。

        该模式中包含的角色及其职责:

抽象工厂角色:任何在模式中创建的对 象的工厂类必须实现这个接口。

具体工厂角色:实现抽象工厂接口的具体工厂类。

抽象产品角色:产品对象的共同父 类或共同拥有的接口。

具体产品角色:实现了抽象产品角色所定义的接口。

        优点:

在简单工厂模式优点的基础上新增:若增加和减少产品子类, 不需修改工厂类,只增加产品子类和工厂子类,符合开闭原则即使产品子类过多, 不会导致工厂类的庞大,利于后期维护。

        缺点:

需要额外的编写代码,增加了工作量。

2.3抽象工厂模式
        概念:

        是生产一系列产品(某个品牌,例如:华为手机,华为汽车),在抽象从工厂中定义生产不同产品,具体工厂负责生产一个公司的系列产品。具体工厂负责生产一个公司的一系列产品。

        基本原理:

        一个具体的工厂负责创建一系列相互关联的产品。会简化 客户端的调一用。并且更换产品系列非常方便,更换一个工厂类即可。

        该模式中包含的角色:

        抽象工厂、具体工厂、抽象产品、具体产品。

        优点:

        获取具体系列产品只需要通过具体系列工厂获取,无序关心创建的细节。

3.原型模式

        在开发过程中,需要创建多个数据相同的对象,每次使用new 创建开销比较大,使用对象克隆,以先创建出来的原型对象为模板进行对象复制,提高创建效率。用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对 象相同的新对象。

例如:建立复制,奖状复制。

原型模式包含如下角色:

        抽象原型类:规定了具体原型对象必须实现的的 clone()方法。

        具体原型类:实现抽象原型类的 clone()方法,它是可被复制的对象。

        访问类:使用具体原型类中的 clone()方法来复制新的对象。

原型模式的克隆分为浅克隆和深克隆:

        浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本 类型属性,仍指向原有属性所指向的对象的内存地址。

        深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原 有对象地址。

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值