以很久没有更新了, 前一段时间一直在看设计模式。一直觉得设计比较重要,因为很多问题如果都是以设计的角度去看,会更容易,先了解它的结构,接口,然后再去了解它的细节。设计也与高质量代码关系重大,之前一直想把设计模式学习一遍,所以前段时间一直在看这方面内容,最近的篇幅应该都是跟设计模式相关,应该是会把之前的体会整理出来。设计模式总的来说只是一种总结出来相对固定的招式,它指导思想还是封装,抽象,组合,单一原则,目标是能够解耦,更加灵活。
今天要说的是与创建一个对象有关的的设计模式,现在一共有5种: 1.工厂方法 2.抽象工厂 3.创建者模式 4.原型模式 5.单例。这次主要聊一下工厂相关的两个: 工厂方法和抽象工厂。
工厂模式的优势是第一封装了对象创建的过程,第二是对于需求方来说,当需要增加创建对象的具体类型不需要更改太多代码,只需要更换创建对象的工厂即可,经常看到的一句话总结叫做 创建和使用分开。把工厂方法和抽象工厂放在一起说,是因为我觉得这两种模式设计代码的方式是一样的,只不过抽象工厂在工厂方法的基础上增加了更多产品类型,创建的产品类型更为复杂。
工厂方法的结构 主要有两个抽象之后的接口,一个是对产品的抽象接口ProductA,还有一个是对工厂的抽象接口Factory。ProductA的主要作用就是为了统一产品自己的方法,具体可能会生产A1,A2..AN,但是它们都需要实现ProductA的协议。对于Factory的作用是为了抽象各种不同的工厂F1,F2...FN,但是都需要实现Factory的协议。
工厂方法 UML图:
![](https://img.haomeiwen.com/i1460909/d41cfa22dc57a4e3.png)
对于使用方来说,关注的重点是自己需要实例化哪些工厂,至于这些工厂创建的具体产品类型是不关注的,因为它关注知道的是有ProdcutA这个协议。因为有了Facotry,实际上对使用方来说,对某个具体工厂的引用也不需要关注它是什么具体的工厂类型,真正需要关心的细节是:你要创建哪种具体的工厂对象。某种具体的工厂类型的对象,意味着它会生产出对应的产品。工厂创建产品的过程以及产品自身的功能实现都封装到了具体的类型,对使用方来说不需要关注,使用方关注的只有协议。
代码示例:
protocol Computer {
func screen() -> String;
func keyboard() -> String;
func mouse() -> String;
func mainMachine() -> String;
func printSelf();
}
extension Computer {
func printSelf() {
print("\(self.screen()), \(self.keyboard()), \(self.mouse()), \(self.mainMachine())");
}
}
protocol ComputerFactory {
func product() -> Computer;
}
enum FactoryMethodSpace {
class XiaomiFactory: ComputerFactory {
func product() -> Computer {
return XiaomiComputer();
}
}
class HPFactory: ComputerFactory {
func product() -> Computer {
return HPComputer();
}
}
class XiaomiComputer: Computer {
func screen() -> String {
return "小米屏幕";
}
func keyboard() -> String {
return "小米键盘";
}
func mouse() -> String {
return "小米鼠标";
}
func mainMachine() -> String {
return "小米机器";
}
}
class HPComputer: Computer {
func screen() -> String {
return "惠普屏幕";
}
func keyboard() -> String {
return "惠普键盘";
}
func mouse() -> String {
return "惠普鼠标";
}
func mainMachine() -> String {
return "惠普主机";
}
}
}
func FactoryMethod() {
let c = FactoryMethodSpace.HPFactory().product();
c.printSelf()
let c2 = FactoryMethodSpace.XiaomiFactory().product();
c2.printSelf()
}
对于抽象工厂而言 其结构增加了对产品接口的类型,因为产品的种类丰富了起来,可能不止一种. 另外对于工厂来说,
因为对应的产品种类增加,所以相应会增加生产产品的方法,抽象工厂中的接口会有Factory, ProductB1, ProductB2,
而Factory中除了有生产B1的方法还会添加生产B2的方法。
抽象工厂 UML图:
![](https://img.haomeiwen.com/i1460909/ca4ccf43cfaea63e.png)
代码示例:
import Foundation
protocol Keyboard {
func printSelf();
}
protocol Mouse {
func printSelf();
}
protocol Factory {
func productKeyboard() -> Keyboard;
func productMouse() -> Mouse;
}
enum AbstractFactorySpace {
class XiaomiFactory: Factory {
func productKeyboard() -> Keyboard {
return XiaomiKeyboard();
}
func productMouse() -> Mouse {
return XiaomiMouse()
}
}
class HPFactory: Factory {
func productKeyboard() -> Keyboard {
return HPKeyboard();
}
func productMouse() -> Mouse {
return HPMouse();
}
}
class XiaomiKeyboard: Keyboard {
func printSelf() {
print("小米键盘");
}
}
class XiaomiMouse: Mouse {
func printSelf() {
print("小米鼠标");
}
}
class HPKeyboard: Keyboard {
func printSelf() {
print("惠普键盘");
}
}
class HPMouse: Mouse {
func printSelf() {
print("惠普鼠标");
}
}
}
func AbstractFactory() {
let f1 = AbstractFactorySpace.XiaomiFactory();
let k1 = f1.productKeyboard();
let f2 = AbstractFactorySpace.XiaomiFactory();
let m2 = f2.productMouse();
k1.printSelf();
m2.printSelf();
}
Reference: Dive Into DESIGN PATTERNS
网友评论