I am new to programming in Swift and I have reached a blocker in constructing a Factory design pattern. Below is my code:
protocol IInterface {
func InterfaceMethod() -> Void
}
public class SubClass: IInterface {
init() {}
func InterfaceMethod() { }
public func SubClassMethod() { }
}
public class Factory() {
class func createFactory() -> IInterface {
return SubClass()
}
}
Finally, i am trying to access it like below
let mgr = Factory.createFactory()
//calling Interface Method
mgr.InterfaceMethod() -- This works, when i keep a dot (mgr.) it shows the method name
//calling subclass method
mgr.SubClassMethod() -- This doesn't work, when i keep a dot (mgr.) it doesnt even show the subclass method name
Even if i use mgr.SubClassMethod
, it throws error saying
Value of type IInterface has no member SubClassMethod
I believe i am getting exposed only with protocol methods though a SubClass object is returned via factory
All the examples I browsed and have seen shows only how to consume methods specified by the protocol, but i haven't seen an example where it shows how to consume a subclass's own methods apart from protocols methods
You miss the point of Factory pattern.
The idea of Factory pattern is to provide methods that have specific return type and return instances that either has this type or inherits from this type (if it's class
type) or conforms to this type (if it's protocol
).
protocol Animal {
func voice() -> String
}
class Dog: Animal {
func voice() -> String {
return "bark"
}
func sit() {
}
}
class Cat: Animal {
func voice() -> String {
return "meow"
}
}
class AnimalFactory {
func getAnimal() -> Animal {
return Dog()
}
}
Client code calling Factory method should not speculate about its return value and try to cast it to concrete class. That's totally ruining the point of using Factory pattern.
As you can see in above example AnimalFactory.getAnimal()
return instance of some type that conforms to Animal
protocol. Code calling this method does not know and should not know about specific type of that instance.
If code calling Factory method expects that returning instance has type Dog
or inherits from this type then you should create and use separate DogFactory
:
class EvilDog: Dog {
override func voice() -> String {
return "bark-bark"
}
}
class DogFactory {
func getDog() -> Dog {
return EvilDog()
}
}
You can have situation when client code implement different behavior dependent on real type of instance that is returned by factory method. In that case
AnimalFactory
should implement methods for providing instances of all types that will be used in client code:
class AnimalFactory {
func getDog() -> Dog {
return EvilDog()
}
func getCat() -> Cat {
return Cat()
}
}
func trainAnimal(iLikeDogs: Bool, animalFactory: AnimalFactory) {
if iLikeDogs {
let dog = animalFactory.getDog()
dog.voice()
dog.sit() // only dog can sit
} else {
let cat = animalFactory.getCat()
cat.voice()
}
}
Actually there are three patterns - Factory, Abstract Factory and Factory method. You can read about differences here.