Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

Swift

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 18, средняя оценка - 4.83
BigDanceMouse
5 / 5 / 1
Регистрация: 26.01.2014
Сообщений: 69
#1

Реализация паттернов - Swift

23.11.2014, 11:38. Просмотров 2494. Ответов 7
Метки нет (Все метки)

Привет!
Изучаю сейчас паттерны для Obj-C, а за одно и немного Swift. Конечно для Swift-а пока-что мало каких-то материалов, но язык мне понравился, так что решил совместить полезное с полезным и изученные паттерны на Obj-C буду переделывать под Swift. Постепенно буду наполнять эту тему и прошу у тех, кто уже разобрался в новом языке - подсказать как их правильнее реализовать. Так что вот мой первый паттерн "Фабричный Метод", написан на основе материала в википедии.

Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class Product {
    var name: String {get{return ""}}
}
 
class ConcreteProductA: Product {
 
    override var name: String{
        get{
            return "ProductA"
        }
    }
}
 
class ConcreteProductB: Product {
 
    override var name: String{
        get{
            return "ProductB"
        }
    }
}
 
class Creator {
    func fuctoryMethod<T:Product>() -> T? {
        return nil
    }
}
 
class ConcreteCreatorA: Creator {
    override func fuctoryMethod<T: Product>() -> T?{
        return ConcreteProductA() as? T
    }
}
 
class ConcreteCreatorB: Creator {
    override func fuctoryMethod<T: Product>() -> T?{
        return ConcreteProductB() as? T
    }
}
 
 
//    использование
let creators = [ConcreteCreatorA(), ConcreteCreatorB()]
for creator in creators {
    if let product = creator.fuctoryMethod(){
        println(product.name)
    }
}
1
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.11.2014, 11:38
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Реализация паттернов (Swift):

Реализация будильника - Программирование iOS
День добрый. Необходимо сделать что то вроде &quot;будильника&quot;. Немного полистав литературы, не нашёл практических примеров реализации для...

Использование паттернов - ООП и паттерны
Приведите, пожалуйста, примеры использования паттернов в ПО, которое известно каждому или которым пользуется почти каждый. Приветствуются...

Задачи на понимание паттернов - ООП и паттерны
Добрый день, форумчане! Изучаю паттерны, читаю книгу &quot;Приемы ООП. Паттерны проектирования&quot; (Э. Гамма, Р. Хелм, Р. Джонсон, Дж....

Правильное использование паттернов - ООП и паттерны
Всем привет. Пишу в этот топик впервые. Недавно начал изучать паттерны, и как раз на носу курсовая(язык Java). В курсовой будет...

Использование паттернов в Делфи - Delphi
Доброе утро всем!)) По сабжу, возможно ли это? И если да, то есть ли литература какая нить. И например в C# классы созданные тобой,...

Физический смысл паттернов - C++
В чем состоится физический смысл паттернов, где найти литературу на эту тему?

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Vorona
Peace 2 all shining faces
668 / 530 / 45
Регистрация: 05.03.2010
Сообщений: 1,283
23.11.2014, 18:13 #2
ну вот например есть https://github.com/ochococo/Design-Patterns-In-Swift

да и T: Product, можно тут просто заменить на возвращаемый тип Product, дженерики тут необязательны

Objective-C
1
func factoryMethod() -> Product? { /* ... */ }
и вместо fuctory, правильно factory
0
BigDanceMouse
5 / 5 / 1
Регистрация: 26.01.2014
Сообщений: 69
23.11.2014, 20:26  [ТС] #3
Vorona,
Цитата Сообщение от Vorona Посмотреть сообщение
дженерики тут необязательны
Да, я сначала именно так и решил сделать. Но начали выскакивать ошибки о несовместимости классов. Возможно, конечно, это была единичная ошибка вызванная сыростью плэйграунда. Но я решил ее использовав дженерик, и дальше не особо заморачивался с этим. Попробую на реальном примере как нибудь.
Цитата Сообщение от Vorona Посмотреть сообщение
ну вот например есть https://github.com/ochococo/Design-Patterns-In-Swift
Да, как раз этим примером я и был "вдохновлен". Но там, на сколько я понял, фабричный метод реализован "не каноническим" путем. За счет использования протокола и enum вместо класса генератора. Или нет?
0
Vorona
Peace 2 all shining faces
668 / 530 / 45
Регистрация: 05.03.2010
Сообщений: 1,283
23.11.2014, 21:31 #4
да все верно, первое время тоже очень непривычно работать с enum в таком стиле, но заметил, что часто где его используют в swift.
И благодаря тому, что он ведет себя, по большому счету, как и любой другой тип и в то же время как enum, то очень просто можно использовать его для реализации pattern matching.

Поскольку swift очень вдохновлен функциональными языками и много где в самом языке продвигается этот подход, то и тут можно провести параллель, например с Haskell, где очень удобно и просто типы участвуют в pattern matching.

Смотрелось бы немного нелепо и неестественно и, возможно, более ресурсоемко делать такую же проверку в switch при помощи as, но благодаря такому сочетанию enum+class, решение выглядит изящно и дешевле.

Впервые увидел на практике такой подход в замечательном фреймворке Alamofire, где для построения роутинга или подобного упрощения конструкции запросов советуют использовать enum.
0
BigDanceMouse
5 / 5 / 1
Регистрация: 26.01.2014
Сообщений: 69
24.11.2014, 12:49  [ТС] #5
Второй вариант фабричного метода. Спасибо Vorona,
Отличия заключаются в отсутсвие дженериков (в более ранних версиях xCode была ошибка при возвращении класса-наследника функцией в которой был объявлен возвращаемым - родительский класс). Также в качестве способа выбора конечного продукта использован enum.
Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class Product {     // можно использовать протокол вместо абстрактного класса
    var name: String {get{return ""}}
}
 
class ConcreteProductA: Product {
 
    override var name: String{
        get{
            return "ProductA"
        }
    }
}
 
class ConcreteProductB: Product {
 
    override var name: String{
        get{
            return "ProductB"
        }
    }
}
 
enum ProductType{
    case aType, bType
}
 
class Creator {
    class func factoryMethod(productType:ProductType) ->Product{
        switch productType{
        case .aType:
            return ConcreteProductA()
        case .bType:
            return ConcreteProductB()
        }
    }
}
 
//    использование
let creators = [ProductType.aType, ProductType.bType]
for creator in creators{
    let product = Creator.factoryMethod(creator)
    println(product.name)
}
0
Vorona
Peace 2 all shining faces
668 / 530 / 45
Регистрация: 05.03.2010
Сообщений: 1,283
26.11.2014, 04:37 #6
Вот еще как вариант, если мы примерно знаем, что особо замудренной логики не будет, а, например как у того парня на гитхабе в примере с валютой, то можно сделать так:
Это, конечно, уже не фабричный метод, но новый язык открывает новые возможности и при чем достаточно удобные и гибкие
Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protocol Product {
    var name: String { get }
}
 
enum ConcreteProduct: Product {
    case ProductA, ProductB, ProductC
    
    var name: String {
        switch self {
            case .ProductA: return "ProductA"
            case .ProductB: return "ProductB"
            case .ProductC: return "ProductC"
        }
    }
}
 
let products = [ConcreteProduct.ProductA, ConcreteProduct.ProductB]
for product in products {
    println(product.name)
}
Поскольку enum ведет себя, как обычный тип, можно создавать такие несложные конструкции, но вести они себя будут по-прежнему как обычные переменные и тип их может полностью определятся протоколом, который они имплементируют, потому в самом коде ничего не поменяется, если вы даже в будущем измените enum на class, ведь параметром в метод или конструктор приходит все та же переменная все того же типа Product

P.S. еще немного синтаксического сахара: если у вас определяется только геттер проперти, то можно опустить обворачивание тела в prop { get {} }, а писать сразу prop { }
и еще есть прикольная штука, когда можно опустить return, но это походу только в колбеках с одной операцией, типа array.map { $0 + "moo" }
1
BigDanceMouse
5 / 5 / 1
Регистрация: 26.01.2014
Сообщений: 69
26.11.2014, 22:42  [ТС] #7
Паттерн Прототип.
Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/* Prototype */
 
protocol Prototype{
    func clone() -> Self
}
 
class SomeInnerClass: Prototype {
    var someString:String
    
    init(){
        self.someString = "string"
    }
    
    init(someString:String){
        self.someString = someString
    }
    
    func clone() -> Self {
        var cloned = self.dynamicType.init(someString:self.someString)
        return cloned
    }
}
 
class ExtClass: Prototype {
    var reference4class = SomeInnerClass()
    
    required init(){    }
    
    func clone() -> Self {
        var cloneObject = self.dynamicType.init()
        cloneObject.reference4class = reference4class.clone()
        return cloneObject
    }
}
 
//    Использование
 
let anotherClass = ExtClass()
anotherClass.reference4class.someString = "anotherString"
 
let clonedObject = anotherClass.clone()
clonedObject.reference4class.someString
0
BigDanceMouse
5 / 5 / 1
Регистрация: 26.01.2014
Сообщений: 69
11.12.2014, 23:22  [ТС] #8
Паттерн Абстрактная Фабрика.
Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/* Abstract Factoru */
 
        /* ПРОДУКТЫ ФАБРИКИ */
 
//    Протокол или абстрактный класс для продуктов
protocol Numbers{
    func numbSet()->[Int]
}
 
 
//    Конкретные продукты разных конкретных фабрик
class PositiveNumbers: Numbers {
    func numbSet() -> [Int] {
        return [1, 2, 3, 4, 5]
    }
}
 
class NegativeNumbers: Numbers {
    func numbSet() -> [Int] {
        return [ -1, -2, -3, -4, -5]
    }
}
 
//    Класс нуля реализован для отображения всего численного диапазона.
//    Может быть использован как абстрактный класс для конкретных продуктов.
class ZeroNumber: Numbers {
    func numbSet() -> [Int] {
        return [0]
    }
}
 
 
        /* ТИП КОНКРЕТНОЙ ФАБРИКИ */
 
enum SignIndicator{
    case Positive, Negative, Zero
}
 
        /* ФАБРИКИ */
 
//    Абстрактная фабрика объявляет интерфейсы для конкретных фабрик, а также
//    создает экземпляр конкретной фабрики для клиента.
class NumbersFactory {
    
    //  Фабричный метод не переопределяется потомками.
    //  Обращиясь к нему, клиент получает экземпляр конкретной
    //  фабрики, на основании заданных настроек
    class final func factoryOfType(sign: SignIndicator) -> NumbersFactory{
        switch sign{
        case .Positive:
            return PositiveNumbersFactory()
        case .Negative:
            return NegativeNumbersFactory()
        default:
            return NumbersFactory()
        }
    }
    
    func sampleNumbers() -> Numbers{
//        возвращаем новый экземпляр конкретного продукта
        return ZeroNumber()
    }
}
 
class PositiveNumbersFactory: NumbersFactory {
    override func sampleNumbers() -> Numbers {
        return PositiveNumbers()
    }
}
 
class NegativeNumbersFactory: NumbersFactory {
    override func sampleNumbers() -> Numbers {
        return NegativeNumbers()
    }
}
 
        /* ИСПОЛЬЗОВАНИЕ */
 
//    обращаемся к абстрактной фабрике для получения экземпляра
var variableFactory = NumbersFactory.factoryOfType(.Positive)
//    экземпляр отвечает на наш тестовый запрос
variableFactory.sampleNumbers().numbSet()
 
//    меняем фабрику
variableFactory = NumbersFactory.factoryOfType(.Negative)
//    экземпляр продолжает отвечать на наш тестовый запрос
variableFactory.sampleNumbers().numbSet()
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.12.2014, 23:22
Привет! Вот еще темы с ответами:

Нужен пример использование паттернов - C++
Мне нужно пример использование паттернов в программах написанных на JAVA или C++ языках!

Иерархия исключений с использованием порождающих паттернов - C++
Вообщем поставлена задача, сделать иерархию исключений для парсера, вроде что то накидал, ну и работает норм, хотелось бы узнать от...

Порядок обработки url паттернов в django - Python
Имеется url такого вида url(r'^archive/$', archive, name='archive'), url(r'^(?P&lt;category&gt;+)/$', category, name='category'), ...

Нужен пример применения паттернов MVC, MVP, MVVM - ООП и паттерны
Я знаю, что они из себя представляют. Но что-то нахожу в них одни неудобства. Эксперимента ради запустил пару проектов - один пишу как...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
11.12.2014, 23:22
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru