目录
- 二、生成器模式
- 1. 生成者模式
- 概念
- 实例一:房屋选购系统
- 题目
- 时序图
- 类图
- 优缺点
- 适用场景
- 2. 生成器模式与抽象工厂模式
- 3. 课程作业***
- 三、单例模式
- 1. 单例模式
- 要点:
- 基本思路
- 实例一:互联网连接问题
- 2. 多线程情况
- 3. 优缺点
- 4. 适用场景
- 5. 课程作业
二、生成器模式
1. 生成者模式
概念
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
生成器模式是一步一步创建一个复杂的对象
Director director = new Director();
director.setBuilder(cb);
director.construct();
if ( cb == 1 ) Product1 = director.getObject();
else Product 2 = director.getObject();
1.确定Director,成员为xxxBuilder(表示要用到的生成器的父类),方法有设置生成器,获取产品(getXXX),创建整个产品的方法(这个方法用来调用生成器的各个方法,最后生成一个完整的产品)指挥者类针对抽象生成器类编程
2.确定XXXBuilder,成员为产品,方法就是构建这个产品所有部件所需的方法,以及getXXX获取产品,以及初始化产品的方法(肯定要先new申明一个空的产品,赋值给成员变量里的产品)
3.确定具体的生成器类,继承自XXXBuilder
4.确定具体产品,成员和方法就是该产品所需的各种方法属性等
实例一:房屋选购系统
题目
时序图
只需要选择一个HouseBuilder,再调用构建的方法constructWholeHouse,再一个个调用生成部件的方法,调用设置参数方法,就能返回产品
类图
Director director = new Director();
director.setHouseBuilder( hb );
director.constructWholeHouseObj();
House hsObj = director.getHouse();
优缺点
优点
- 在生成器模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
- 每一个具体生成器都相对独立,而与其他的具体生成器无关,因此可以很方便地替换具体生成器或增加新的具体生成器,用户使用不同的具体生成器即可得到不同的产品对象。
- 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
- 增加新的具体生成器无须修改原有类库的代码,指挥者类针对抽象生成器类编程,系统扩展方便,符合“开闭原则”。
缺点
- 生成器模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用生成器模式,因此其使用范围受到一定的限制。
- 如果产品的内部变化复杂,可能会导致需要定义很多具体生成器类来实现这种变化,导致系统变得很庞大。
适用场景
- 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
- 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
- 对象的创建过程独立于创建该对象的类。在生成器模式中引入了指挥者类,将创建过程封装在指挥者类中,而不在生成器类中。
- 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
2. 生成器模式与抽象工厂模式
- 与抽象工厂模式相比,生成器模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
- 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在生成器模式中,客户端可以不直接调用生成器的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。
- 如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么生成器模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车。
3. 课程作业***
三、单例模式
1. 单例模式
单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供一个全局访问点。
要点:
某个类只能有一个实例
它必须自行创建这个实例
它必须自行向整个系统提供这个实例
基本思路
instance是静态变量,类型为Singleton,用于存储已经被创建的实例。getInstance()为实例创建方法,它创建实例的方式很特别,如果一个实例此前已经被创建了(因而被存储在变量instance中),则该方法返回instance;如果此前Single实例没有被创建,则该方法新创建并且返回Singleton类的一个实例,从而保证了实例的唯一性。
Public class Singleton {
private static Singleton instance;
private String name;
private Singleton (String name) {
this.name = name;
}
public static Singleton getInstance (String name) {
if (instance == null && ! name.equals(null))
instance = new Singleton (name);
return instance;
}
}
实例一:互联网连接问题
2. 多线程情况
多线程中的单例模式,在getInstance()方法应声明为synchronized,防止当唯一实例尚未创建时有两个线程同时调用创建方法,那么将导致两个现成各自创建了一个实例,从而违反了单例模式的实例唯一性的初衷
3. 优缺点
优点
- 提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它,并为设计及开发团队提供了共享的概念。
- 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。
- 允许可变数目的实例。我们可以基于单例模式进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例。
缺点
- 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
- 单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。
- 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;现在很多面向对象语言(如Java、C#)的运行环境都提供了自动垃圾回收的技术,因此,如果实例化的对象长时间不被利用,系统会认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致对象状态的丢失。
4. 适用场景
- 系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器,或者需要考虑资源消耗太大而只允许创建一个对象。
- 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。
- 在一个系统中要求一个类只有一个实例时才应当使用单例模式。反过来,如果一个类可以有几个实例共存,就需要对单例模式进行改进,使之成为多例模式。
5. 课程作业