# 设计模式 **Repository Path**: DencyCheng_admin/design_pattern ## Basic Information - **Project Name**: 设计模式 - **Description**: java 设计模式案例 - **Primary Language**: Java - **License**: AFL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2019-12-03 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 设计模式-工厂模式 ## 软件架构 软件架构说明 工厂模式 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。 ## 介绍 **意图**:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。 **主要解决**:主要解决接口选择的问题。 **何时使用**:我们明确地计划不同条件下创建不同实例时。 **如何解决**:让其子类实现工厂接口,返回的也是一个抽象的产品。 **关键代码**:创建过程在其子类执行。 **应用实例**: - 您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。 - Hibernate 换数据库只需换方言和驱动就可以。 **优点**: - 一个调用者想创建一个对象,只要知道其名称就可以了。 - 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 - 屏蔽产品的具体实现,调用者只关心产品的接口。 **缺点**: 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。 **使用场景**: - 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 - 数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 - 设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。 **注意事项**:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。 --- # 设计模式-单例模式 ## 软件架构 软件架构说明 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。 注意: - 单例类只能有一个实例。 - 单例类必须自己创建自己的唯一实例。 - 单例类必须给所有其他对象提供这一实例。 ## 介绍 **意图**:保证一个类仅有一个实例,并提供一个访问它的全局访问点。 **主要解决**:一个全局使用的类频繁地创建与销毁。 **何时使用**:当您想控制实例数目,节省系统资源的时候。 **如何解决**:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。 **关键代码**:构造函数是私有的。 **应用实例**: - 一个班级只有一个班主任。 - Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。 - 一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。 **优点**: - 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。 - 避免对资源的多重占用(比如写文件操作)。 **缺点**: 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。 **使用场景**: - 要求生产唯一序列号。 - WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。 - 创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。 **注意事项**:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。 --- # 设计模式-策略模式 ## 软件架构 软件架构说明 策略模式 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。 ## 介绍 **意图**:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。 **主要解决**:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。 **何时使用**:一个系统有许多许多类,而区分它们的只是他们直接的行为。 **如何解决**:将这些算法封装成一个一个的类,任意地替换。 **关键代码**:实现同一个接口。 **应用实例**: - 诸葛亮的锦囊妙计,每一个锦囊就是一个策略。 - 旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。 - JAVA AWT 中的 LayoutManager。 **优点**: - 算法可以自由切换。 - 避免使用多重条件判断。 - 扩展性良好。 **缺点**: - 策略类会增多。 - 所有策略类都需要对外暴露。 **使用场景**: - 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 - 一个系统需要动态地在几种算法中选择一种。 - 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。 **注意事项**:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。 # 设计模式-观察者模式 ## 软件架构 观察者模式 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 ## 介绍 **意图**:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 **主要解决**:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。 **何时使用**:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。 **如何解决**:将这些算法封装成一个一个的类,任意地替换。 **关键代码**:使用面向对象技术,可以将这种依赖关系弱化。 **应用实例**: - 拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。 - 西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作。 **优点**: - 观察者和被观察者是抽象耦合的 - 建立一套触发机制。 **缺点**: - 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 - 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 - 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。 **使用场景**: - 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。 - 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。 - 一个对象必须通知其他对象,而并不知道这些对象是谁。 - 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。 **注意事项**: - JAVA 中已经有了对观察者模式的支持类 - 避免循环引用 - 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。