文章目录
- 一、创建型模式
- 1. 包含模式
- 1.1 工厂模式
- 1.2 建造者模式
- 1.3 原型模式
- 1.4 单例模式
- 二、工厂模式
- 1. 概要
- 1.1 意图
- 1.2 主要解决问题
- 1.3 何时使用
- 1.4 如何解决
- 1.5 关键代码
- 1.6 使用场景
- 1.7 优点
- 1.8 缺点
- 1.9 简单工厂实现
- 2. 简单工厂模式
- 2.1 模式结构
- 2.2 实例
- 2.3 模式定义
- 2.4 模式分析
- 2.5 适用情况
- 2.6 特点
- 2.6.1 优点
- 2.6.2 缺点
一、创建型模式
创建型模式对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用分离。
为了使软件的结构更加清晰,外界对于这些对象只需要知道它们共同的结构,而不清楚其具体的实现细节,使整个系统的设计更加符合单一职责原则。
创建型模型在创建什么(What),由谁创建(Who),何时创建(When)等方面都为软件设计者提供了尽可能大的灵活性。
创建型模式隐藏了类的实例的创建细节,通过隐藏对象如何被创建和组合在一起达到使整个系统独立的目的。
1. 包含模式
1.1 工厂模式
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
1.2 建造者模式
1.3 原型模式
1.4 单例模式
二、工厂模式
工厂模式是最常用的设计模式之一,提供了一种创建对象的方式,使得对象的创建过程与对象的使用过程分离。
工厂模式提供了一种创建对象的方式,而无需指定要创建的具体类。
通过使用工厂模式,可以将对象的创建逻辑封装在一个工厂类中,而不是在客户端代码中直接实例化对象,这样可以提高代码的可维护性和可扩展性。
1. 概要
概要内容偏书面化,读起来有点绕,看看代码实现就很容易理解啦~~我个人体验概要不需要读,直接看代码也能明白做法的意图啦
1.1 意图
定义一个创建对象的接口,让其子类决定实例化哪一个具体的类。工厂模式使对象的创建过程延迟到子类。
1.2 主要解决问题
接口选择的问题。
1.3 何时使用
当需要在不同条件下创建不同实例时。
1.4 如何解决
通过让子类实现工厂接口,返回一个抽象的产品。
1.5 关键代码
对象的创建过程在子类中实现。
1.6 使用场景
- 日志记录:日志可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志的位置。
- 数据库访问:当用户不知道最终系统使用哪种数据库,或者数据库可能变化时。
- 连接服务器的框架设计:需要支持 “POP3”、“IMAP”、“HTTP” 三种协议,可以将这三种协议作为产品类,共同实现一个接口。
1.7 优点
- 调用者只需要知道对象的名称即可创建对象。
- 扩展性高,如果需要增加新产品,只需扩展一个工厂类即可。
- 屏蔽了产品的具体实现,调用者只关心产品的接口。
1.8 缺点
每次增加一个产品时,都需要增加一个具体类和对应的工厂,使系统中类的数量成倍增加,增加了系统的复杂度和具体类的依赖。
1.9 简单工厂实现
创建一个 Shape 接口和实现 Shape 接口的实体类。下一步是定义工厂类 ShapeFactory。
FactoryPatternDemo 类使用 ShapeFactory 来获取 Shape 对象。它将向 ShapeFactory 传递信息(CIRCLE / RECTANGLE / SQUARE),以便获取它所需对象的类型。
package main
import "fmt"
// Shape 接口
type Shape interface {
Draw()
}
// Rectangle 结构体
type Rectangle struct{}
// Draw 方法实现
func (r *Rectangle) Draw() {
fmt.Println("Inside Rectangle::draw() method.")
}
// Square 结构体
type Square struct{}
// Draw 方法实现
func (s *Square) Draw() {
fmt.Println("Inside Square::draw() method.")
}
// Circle 结构体
type Circle struct{}
// Draw 方法实现
func (c *Circle) Draw() {
fmt.Println("Inside Circle::draw() method.")
}
// ShapeFactory 结构体
type ShapeFactory struct{}
// GetShape 方法
func (f *ShapeFactory) GetShape(shapeType string) Shape {
switch shapeType {
case "CIRCLE":
return &Circle{}
case "RECTANGLE":
return &Rectangle{}
case "SQUARE":
return &Square{}
default:
return nil
}
}
// 主函数
func main() {
shapeFactory := &ShapeFactory{}
// 获取 Circle 的对象,并调用它的 Draw 方法
shape1 := shapeFactory.GetShape("CIRCLE")
shape1.Draw()
// 获取 Rectangle 的对象,并调用它的 Draw 方法
shape2 := shapeFactory.GetShape("RECTANGLE")
shape2.Draw()
// 获取 Square 的对象,并调用它的 Draw 方法
shape3 := shapeFactory.GetShape("SQUARE")
shape3.Draw()
}
2. 简单工厂模式
2.1 模式结构
简单工厂模式包含如下角色:
1. Factory:工厂角色
工厂角色负责实现创建所有实例的内部逻辑。
2. Product:抽象产品角色
抽象产品角色是所创建的所有对象的父类,负责描述所有实例所共有的公共接口。
3. ConcreteProduct:具体产品角色
具体产品角色是创建目标,所有创建的对象都充当这个角色的某个具体类的实例。
2.2 实例
工厂类负责创建对象,客户端只需调用工厂方法。
package main
import "fmt"
// Shape 接口
type Shape interface {
Draw()
}
// Circle 结构体
type Circle struct{}
func (c *Circle) Draw() {
fmt.Println("Drawing a Circle")
}
// Rectangle 结构体
type Rectangle struct{}
func (r *Rectangle) Draw() {
fmt.Println("Drawing a Rectangle")
}
// ShapeFactory 简单工厂
type ShapeFactory struct{}
func (f *ShapeFactory) GetShape(shapeType string) Shape {
switch shapeType {
case "CIRCLE":
return &Circle{}
case "RECTANGLE":
return &Rectangle{}
default:
return nil
}
}
// 主函数
func main() {
factory := &ShapeFactory{}
shape1 := factory.GetShape("CIRCLE")
shape1.Draw()
shape2 := factory.GetShape("RECTANGLE")
shape2.Draw()
}
2.3 模式定义
简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。
在简单工厂模式中,可以根据参数的不同返回不同类的实例。
简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
2.4 模式分析
- 将对象的创建和对象本身业务处理分离可以降低系统的耦合度,使得两者修改起来都相对容易。
- 在调用工厂类的工厂方法时,由于工厂方法是静态方法,使用起来很方便,可通过类名直接调用,而且只需要传入一个简单的参数即可,在实际开发中,还可以在调用时将所传入的参数保存在XML等格式的配置文件中,修改参数时无须修改任何源代码。
- 简单工厂模式最大的问题在于工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,这一点与开闭原则是相违背的。
- 简单工厂模式的要点在于:当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。
2.5 适用情况
- 工厂类负责创建的对象比较少:由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
- 客户端只知道传入工厂类的参数,对于如何创建对象不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。
2.6 特点
2.6.1 优点
- 工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。
- 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。
- 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
2.6.2 缺点
- 由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
- 使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
- 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
- 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。