Single Responsibility Principle(Only one factor to change)
Class Level
Method Level
Open-Closed principle
subclass can inherit from superclass, it can override some thing. However, subclass cannot how the superclass implements method.
For Example, subclass cannot know the implementation of superclass method. However subclass can call the method of superclass
Liskov substitution principle (里氏替换)
- subclass can replace its superclass
// For example
// act as a superclass
protocol BaseProtocol {
func hehe()
}
extension BaseProtocol {
func hehe() {
print("BaseProtocol.hehe()")
}
}
// act as a subclass
class Base: BaseProtocol {
func hehe() {
print("Base.hehe()")
}
}
// Liskov substitution func
func call(base: BaseProtocol) {
base.hehe()
}
call(base: Base())
// print Base.hehe()
Interface Segregation principle (接口隔离)
Dependency Inversion Principle
A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend on details. Details should depend on abstractions.
from http://clean-swift.com/dependency-inversion-a-little-swifty-architecture/#more-124
// MARK: - service provide abstraction
protocol Service {
func fetchUserWithID(id: String, completionHandler: (user: User?, error: ErrorType?) -> ())
}
// MARK: - sender rely on service abstraction instead of a concrete class implementation
class Sender {
private var service: Service
// MARK: - constructor dependency injection
init(s: Service) {
service = s
}
func doSomething() {
service.fetchUserWithID("asdf") { (user: User?, error: ErrorType?) in
// Do something with the user
}
}
}
// MARK: - a concrete class implement the service abstraction
class ParseService: Service {
func fetchUserWithID(id: String, completionHandler: (user: User?, error: ErrorType?) -> ()) {
// Do the fetch
// Map PFObject into User
// Ivoke completionHandler
}
}
// MARK: - if we want to assign service abstraction into sender
let parseService = ParseService()
let sender = Sender(parseService)
First, it defines Service. A concrete class that conforms to this protocol must implement the methods
Sender defines a private service variable of service. The initializer also accepts service used to set this variable. Again, constructor dependency injection is at work here.
Why is important?
if The receiver variable is of a concrete specific service, and you invoke its fetchUserWithID method directly. This means the high level Sender depends on the low level specific receiver.
Why is this bad? Because if you were to change theSpecificReceiver, you would have to change theSenderas well.
Factory Pattern
- define protocol to describe the common interface
- class/struct/enum conform this protocol and provide implementation
- Once we need to call the common interface, we dont care the type of passed in object, we just concern whether it conforms the protocol
- Replace some inheritance scene/scenario
- Replace some multiple inheritance, avoiding Diamond Problem
Singleton Pattern
- one instance in the whole process
- one instance is global
- initialize once, drop the dup init trial, possible Thread-safe problem
class SingletonManager {
private init() { }
static let shared = SingletonManager()
}