《创建型设计模式》
创建型模式抽象了实例化过程,他们帮助一个系统独立于如何创建、组合和表示它的那些对象。
-
一个类创建型模式使用继承改变被实例化的类。
-
一个对象创建型模式将实例化委托给另一个对象。
1、单例模式
简介:
-
单例模式:
- 单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。
- 单例模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建,这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象
-
意图:
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
-
主要解决:
- 一个全局使用的类频繁地创建与销毁
- 当您想控制实例数目,节省系统资源的时候
适用场景:
- Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行
- 一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件
- WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来
- 创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等
结构:
- 创建一个 SingleObject 类,SingleObject 类有它的私有构造函数和本身的一个静态实例 SingleObject 类提供了一个静态方法,供外界获取它的静态实例
- SingletonPatternDemo 使用 SingleObject 类来获取 SingleObject 对象
代码实现:
最好理解的一种模式,分为懒汉式和饿汉式
/**
* 饿汉式
*/
public static class hungrySingleton {
// 直接创建对象
public static hungrySingleton instance = new hungrySingleton();
// 私有化构造函数
private hungrySingleton() {
}
// 提供对外方法
public static hungrySingleton getInstance() {
return instance;
}
}
/**
* 懒汉式
*/
public static class LazySingleton {
// 声明变量
private static volatile LazySingleton singleton= null;
// 私有构造函数
private LazySingleton() {
}
// 提供对外方法
public static synchronized LazySingleton getInstance() {
if (singleton == null) {
singleton = new LazySingleton();
}
return singleton;
}
}
2、工厂方法模式
简介:
-
举例:
- 追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的Factory
-
工厂模式:
- 客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:如何创建及如何向客户端提供。
- 定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行
-
主要解决:
- 主要解决接口选择的问题
-
何时使用:
- 我们明确地计划不同条件下创建不同实例时
-
如何解决:
- 让其子类实现工厂接口,返回的也是一个抽象的产品
适用场景:
- 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方
- 数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时
- 设计一个连接服务器的框架,需要三个协议,“POP3”、“IMAP”、“HTTP”,可以把这三个作为产品类,共同实现一个接口
结构:
-
创建一个 Shape 接口和实现 Shape 接口的实体类
-
下一步是定义工厂类 ShapeFactory
-
FactoryPatternDemo 使用 ShapeFactory 来获取 Shape 对象
它将向 ShapeFactory 传递信息( CIRCLE / RECTANGLE / SQUARE ),以便获取它所需对象的类型
代码实现:
1、创建一个接口
public interface Shape {
void draw();
}
2、创建实现接口的实体类
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
3、创建一个工厂,生成基于给定信息的实体类的对象
public class ShapeFactory {
//使用 getShape 方法获取形状类型的对象
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
}
4、使用该工厂,通过传递类型信息来获取实体类的对象
public class FactoryPatternDemo {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
//获取 Circle 的对象,并调用它的 draw 方法
Shape shape1 = shapeFactory.getShape("CIRCLE");
//调用 Circle 的 draw 方法
shape1.draw();
//获取 Rectangle 的对象,并调用它的 draw 方法
Shape shape2 = shapeFactory.getShape("RECTANGLE");
//调用 Rectangle 的 draw 方法
shape2.draw();
//获取 Square 的对象,并调用它的 draw 方法
Shape shape3 = shapeFactory.getShape("SQUARE");
//调用 Square 的 draw 方法
shape3.draw();
}
}
3、抽象工厂模式
简介:
-
举例:
- 请MM去麦当劳吃汉堡,不同的MM有不同的口味,要每个都记住是一件烦人的事情,我一般采用Factory Method模式,带着MM到服务员那儿,说“要一个汉堡”,具体要什么样的汉堡呢,让MM直接跟服务员说就行了。
-
工厂方法模式:
- 核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
- 是实例工厂的父入口。
-
目的:
- 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。