书蒙尘

V1

2022/03/13阅读:36主题:默认主题

设计模式_么么哒

一个好的系统实现 可维护性可复用性 在设计应该具备如下三个性质:

  • 可扩展性:容易将新的功能添加到现有系统中,与“过于僵硬”相对应。
  • 灵活性:修改代码时不会波及很多其他模块,与“过于脆弱”相对应。
  • 可插入性:可以方便地将一个类抽取出去,同时将另一个有相同接口的类添加进来,与“粘度过高”相对应。

七大原则:

  1. 单一指责原则: 一个类只负责一个功能领域的相应职责。
  2. 开闭原则: 对修改关闭,对扩展开放。
  3. 里氏代换原则: 如果能使用基类对象,那么一定能使用其子类对象。
  4. 依赖倒转原则: 抽象应该不依赖于细节,细节应该以来于抽象;要针对接口编程,不要针对实现编程。
  5. 接口隔离原则: 不应该依赖它不要的接口,即将大的接口细化为小的接口提供使用。
  6. 合成复用原则: 尽量使用对象组合,而不使用继承。
  7. 迪米特法则: 一个模块应尽可能少直接与其他模块发生作用,可通过中间控制器来调用。

创建型模式【Creational Pattern】(5种)

1、简单工厂模式(Simple Factory Pattern) -> 工厂方法模式 (Factory Method Pattern)

  • 简单工程模式:又称为静态工厂模式。
  • 在实际软件开发中,有时需要创建一些相同父类的实例,为此可以专门定义一工厂类来负责创建这些类的实例。在这种情况下,可以通过传入不同的参数从而获得不同的对象,利用Java语言特征,习惯将创建其他类的实例定义为static方法,外部不需要实例化这个工厂类就能直接创建实例类。


  • 工厂方法模式:是对简单工厂模式的进一步抽象和推广,克服了简单工厂模式的不够灵活,在增加新的产品时需要改工厂类的判断逻辑,修改代码的违反开闭原则的缺点。
  • 工厂类不在负责所有产品的创建,而是将具体创建工作交给子类去做。

2、抽象工厂模式(Abstract Factory Pattern)

  • 抽象工厂模式是工厂方法的泛化版,工厂方法模式是一种特殊的抽象工厂模式。在工厂方法模式中,每一个具体工厂只能生产一种具体产品,而在抽象工厂方法中,每一个具体工厂可以生产多个具体产品。
  • 如一个电器工厂可以产生多种类型的电器,如海尔工厂可以生产海尔电视机、海尔空调等,Tcl工厂可以生产TCL电视机,TCL空调等,相同品牌的电器构成一个产品族,而相同类型的电器构成一个产品等级结构。

3、建造者模式(Builder Pattern)

  • 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一步一步创建一个复杂的对象,它允许用户只通过制定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。
  • 如KFC创建套餐:套餐是一个复杂对象,它一般包含主食(如汉堡、鸡肉卷)和(饮料、可乐)等组成部分,不同的套餐有不同的组成部分,而KFC的服务员可以根据顾客的要求,一步一步装配这些组成部分,构造一份完整的套餐,然后返回给顾客。

4、原型模式(Phototype Pattern)

  • 为了简化创建过程,可以只需要创建一个对象,然后通过克隆方式复制出多个相同的对象。原型模式的基本工作原理是通过一将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象复制原型来实现创建过程。克隆分为浅克隆和深克隆:
  • 浅克隆:只克隆所考虑的对象,而不复制它所引用的对象,也就是其中的成员对象并不复制。
  • 深克隆:深克隆把要复制的对象所引用的成员对象也都复制了一遍。
public class Email implements Serializable {
    private Attachment attachment;

    public Email() {
        this.attachment = new Attachment();
    }
    public Object deepClone() throws IOException, ClassNotFoundException {
        //需要将使用流来实现深克隆
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bao);
        oos.writeObject(this);

        ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
    }

    public Attachment getAttachment() {
        return attachment;
    }
    public void display(){
        System.out.println("查看邮件");
    }
}

5、单例模式(Singleton Pattern)

  • 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问。分为饿汉式单例和懒汉式单例。

  • 饿汉式:在类加载时就初始化实例。构造函数私有话,避免外界利用构造函数创建更多实例。

  • 懒汉式:构造函数也私有化,但是在第一次引用时将自己实例化。饿汉式在资源利用效率上不如懒汉式,单懒汉式在初始化实例时有可能耗费大量时间,意味着可能多个线程在此期间引用,需要做好同步化机制进行控制。


结构型模式【Structural Pattern】(7种)

1、适配器模式(Adapter Pattern)

  • 用于将一个接口转换为客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器。适配器模式既可以作为类结构模型,也可以作为对象结构模型。
  • 适配器模式包含四个角色:目标抽象类定义客户要用的特定领域的接口;适配器类可以调用另一个接口,作为一个转化器,对适配器和抽象目标类进行适配,它是适配器模式的核心;适配者类是被适配的角色,它定义了一个已经存在的接口,这个接口需要适配;在客户类针对目标抽象类进行编程,调用在目标抽象类中定义的业务方法。
  • 如现在需要设计一个可以模拟各种动物行为的机器人,在机器人中定义类一系列方法,如机器人叫喊方法cry()、机器人移动方法move()等。如果希望在不修改已有代码的基础上使得机器人能狗像狗一样跑可以使用适配器模式进行系统设计。

2、桥接模式(Bridge Pattern)

  • 将抽象部分与它的实现部分分离,使他们都可以独立的变化。比如我们需要5种颜色和3种笔,我们在进行选择时就要3x5=15个类,采用桥接模式,我们则只需要5+3=8个类。

3、组合模式(Composite Pattern)

  • 组合模式用于组合多个对象形成树形结构以表示“整体-部分”。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性。它会定义一个抽象构件类,它既代表叶子,又可以代表容器,而客户端针对构件类编程,无需知道它到底是叶子还是容器,可以对其进行统一管理。
  • 如在水果盘(Plate)中有一些水果,如苹果(Apple)、香蕉(Banana)、梨子(Pear),当然大水果盘中还可以有小水果盘。现需要对盘中遍历吃,当然如果对一个水果盘执行吃的方法,实际上就是吃其中的水果。

4、装饰模式(Decorator Pattern)

  • 可以在不改一个对象的基础上给对象增加额外的新行为。就增加对象功能来说,装饰模式比生成子类实现更为灵活。其别名也可以称为包装器(Responsibility),就增加对象功能来说,与适配器模式的别名相同,但它们适用于不同的茶喝。
  • 如变形金刚在变形之前是一辆汽车,它可以在陆地上移动。当它变成其人之后除了能狗仔陆地上移动之外还可以说话;如果需要,它还可变成飞机,除了在陆地上移动还可以在天空中翱翔。

5、外观模式(Facade Pattern)

  • 外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统种的一组接口提供一个一致的界面,外观模式定义类一个高层接口,这个接口使得一个子系统更加容易使用。
  • 如果没有外观角色,即没有为网站提供一个首页,每个用户需要记住所有子栏目的URL。有了外观角色,用户只需要和外观角色交互,让外观角色与子角色交互。
  • 如现在考察一个电源总开关的例子。为了使用方便,一个电源总开关可以控制四盏灯、一个风扇、一台空调和一台电视机的启动和关闭。通过该电源总开关可以同时控制所有上述电器设备。

6、享元模式(Flyweight pattern)

  • 运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用
  • 很多网络设备都是支持共享的,如交换机,集线器等,多台计算机的终端可以连接同一台网络设备,并通过该网络进行数据转发。但是分配给每一个终端计算机的端口是不同的。可以将端口从网络设备中抽取出来作为外部状态,需要时再进行设置。

)


7、代理模式(Proxy Pattern)

  • 给某个对象提供一个代理,并由代理对象控制对对象的引用。
  • 在一个论坛中已注册的用户和游客的权限不同,已注册的用户拥有发帖,修改自己的注册信息,修改自己帖子等功能;而游客只能看帖子,没有其他权限。使用代理模式中的保护代理,该代理用户控制对一个对象的访问,可以给不同的用户提供不同的使用权限。

行为型模式【Structural Pattern】(11种)

1、职责链模式(Chain of Responsibility Pattern)

  • 避免请求发送者和接受者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿这条链传递请求,知道有对象处理它为止。
  • 如某OA系统需要提供一个假条审批模块,如果员工请假天数小于3天,主任可以审批请假条;若天数大于三天小于10天,经理可以审批;如果员工请假天数大于10天小于30天,总经理可以审批;如果超过30天,总经理也不能审批,提示拒绝相关信息。

2、命令模式(Command pattern)

  • 将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。
  • 如电视机是请求的接收者,遥控器是请求的发起者,遥控器上有一些按钮,不同的按钮对应电视机不同的操作。抽象命令角色由一个命令接口来扮演,有三个具体的命令类实现了抽象的命令接口,这个具体命令类分别表示三种操作:打开电视机,关闭电视机和切换频道。

3、解释器模式(Interpreter Pattern)

  • 主要用于面向语言开发的编译器和解释器的设计。在某些情况下,为了更好的描述某一些特定类型的问题,可以创建一个新的语言,这个语言拥有自己的表达式和结构,即语法规划,而且可以根据需要灵活地增加新的语法规则。此时,可以用解释器模式来设计这种新的语言。

4、迭代器模式(Iterator Pattren)

  • 一个聚合对象,如一个列表(List)或者一个集合(Set),应该提供一种方法来让别人剋访问它的元素,而有不需要暴露它的内部结构。此外,针对不同的需要,可能还要以不同的方式遍历整个聚合对象,但是我们并不希望在聚合对象的抽象层接口中充斥着各种不同遍历的操作。在迭代器模式中,提供一个外部的迭代器来对聚合对象进行访问和遍历,迭代器定义了一个访问该聚合元素的接口,并且可以跟踪当前遍历的元素。
  • 电视机遥控器就是一个迭代器实例,通过它可以实现对电视机频道集合的遍历操作。

5、中介者模式(Mediator Pattern)

  • 用一个中介对象来封装一系列的对象交互,中介对象使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立的改变它们之间的交互。
  • 如某系统欲增加一个虚拟聊天室,允许论坛会员通过该聊天室进行信息交流,普通会员可以给其他会员发送文本信息,钻石会员既可以发送文本信息也可以发送图片信息。该聊天室可以对不雅文字进行过滤,如“日”等自负;还可以对发送的图片进行大小控制。


6、备忘录模式(Memento Pattern)

  • 在不破会封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存状态。并且这个这个状态不能被这个对象和负责人以外的对象访问。
  • 如某系统提供了用户信息操作模块,用户可以修改自己的各项信息。为了使操作过程更佳人性画,现使用备忘录模式对系统进行改进,使得用户在进行了错误的操作之后可以恢复到之前的状态。

7、观察者模式(Observer Patter)

  • 定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式,模式-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
  • 假设猫是老鼠和狗的观察目标,老鼠和狗是观察者,猫叫老鼠跑,狗也跟着叫。

8、状态模式(State Pattern)

  • 在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的对象。在通常情况下,可以用复杂的条件判断 (如if..else) 来进行状态的判断和转换操作,这会导致代码的可维护性和灵活性下降,特别出现新的状态时,代码的可扩展性很差,客户端代码也需要进行相应的修改,违反了“开闭原则”。
  • 状态模式的动机就是允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
  • 如某论坛系统中,用户可以发表留言,发表留言将增加积分;用户也可以回复留言,回复留言也将增加积分;用户还可以下载文件,下载文件将扣除积分。该系统用户可以分为三个等级,分别是新手、高手和专家,这三个等级对应三种不同的状态。

9、策略模式(Strategy Pattern)

  • 在软件系统中,有许多算法可以实现某一功能,如查找、排序等你,一种常用的方法是硬编码在一个类中,如需要提供多种查找算法,每一个方法对应一种具体的算法;也可以将这些查找算法封装在一个统一的方法中,通过if...else...等条件判断语句来进行选择。但是当需要增加一种新的查找算法,需要修改封装算法类的源代码;更换查找算法,也需要修改客户端调用代码,非常难维护。
  • 为了解决这些问题,可以定义 一些独立的类来封装不同的算法,每一个类封装一个具体的算法,在这里,每一个封装算法的类我们可以称之为策略,为了保证这些策略的一致性,一般会用一个抽象的策略类来做算法的定义,而每一个算法对应于一个具体策略类。

10、模版方法模式(Template Mothod Pattern)

  • 定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以不改变一个算法的结构即可以重定义该算法的某一些特定步骤。
  • 如在银行办理业务时,一般都包含几个基本步骤,首先需要取号排队,然后办理具体业务,最后需要对银行工作人员进行评分。无论具体业务时取款、存款还是转账,其基本流程都一样。

11、访问者模式(Visitor Pattern)

  • 对于系统中的某些对象,他们存储在同一个集合中,且具有不同类型,而且对于该集合中的对象,可以接受一类称为访问者的对象来访问,不同的访问者其访问方式有所不同。
  • 如顾客在超市中将选择的商品,如苹果、图书等放在购物车中,然后到收银员处付款。在购物过程中,顾客需要对这些商品进行访问,以便确认这些商品的质量,之后收银员计算价格时也需要访问购物车内顾客所选择的商品。此时,购物车作为一个ObjectStructure(对象结构)用于存储各种类型的商品,而顾客和收银员作为访问这些商品的访问者,他们需要对商品进行检查和计价。不同类型的商品其访问形式也可能不同,如苹果需要过秤之后再计价,而图书不需要。

分类:

后端

标签:

后端

作者介绍

书蒙尘
V1