工厂模式和抽象工厂模式_使用代理和抽象工厂模式快速查看可选视图

工厂模式和抽象工厂模式

Optional views are present in many apps of all kinds. There are 1000 reasons for needing to show or hide a view based on a condition such as app state, user profile, feature/product availability, A/B testing, etc.

在各种类型的许多应用程序中都存在可选视图。 有1000个需要显示或隐藏视图的原因 基于条件,例如应用程序状态,用户个人资料,功能/产品可用性,A / B测试等。

There are also many ways of tackling this issue, but we could split them into three groups, based on which component is responsible for this logic.

解决此问题的方法也有很多,但是我们可以根据负责此逻辑的组件将它们分为三类。

  • Container/optional view’s parent: It comes up as the first option because it seems the easiest and simplest way. And it might be, indeed, in simple cases. However, it becomes messy as the logic grows, or the optional views are reused in other places.

    容器/可选视图的父级:它是第一个选项,因为它似乎是最简单的方法。 实际上,在简单的情况下也可能如此。 但是,随着逻辑的增长,它变得混乱,或者可选视图在其他地方被重用。
  • The optional view itself: Again, a factory method within the optional view itself might be an easy way in simple cases. However, the view should not be responsible for knowing whether it should be shown or not. It should be an assertion.

    可选视图本身:同样,在简单情况下,可选视图本身内的工厂方法可能是一种简便方法。 但是,视图不应负责知道是否应显示该视图。 这应该是一个断言。
  • Other class/factory: Logic comes out of the container/optional view’s parent to a new class whose responsibility is instantiating the view only when it should be shown.

    其他类/工厂:逻辑从容器/可选视图的父级传到一个新类,该类负责仅在应显示该视图时实例化该视图。

Let’s explore the third group since it will serve us well in more contexts.

让我们探讨第三组,因为它可以在更多情况下为我们服务。

具体工厂方法模式 (Concrete Factory Method Pattern)

The first approach we could take is to use a concrete factory method pattern and maintain a reference to both factory and OptionalView.

我们可以采用的第一种方法是使用具体的工厂方法模式并维护对factory和OptionalView的引用。

Image for post
import UIKit


class OptionalView: UIView {
    func viewDidLoad() {}
    func viewWillAppear() {}
}


protocol OptionalViewFactoryProtocol {
    func makeOptionalView() -> OptionalView?
}


struct OptionalViewFactory: OptionalViewFactoryProtocol {
    func makeOptionalView() -> OptionalView? {
        // Conditions
        return OptionalView()
    }
}


class ContainerViewController: UIViewController {
    let optionalViewFactory: OptionalViewFactoryProtocol
    var optionalView: OptionalView?
    
    init(optionalViewFactory: OptionalViewFactoryProtocol) {
        self.optionalViewFactory = optionalViewFactory
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        if let optionalView = optionalViewFactory.makeOptionalView() {
            self.optionalView = optionalView
            view.addSubview(optionalView)
            optionalView.viewDidLoad()
        }
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        optionalView?.viewWillAppear()
    }
}

There are a few things that can be improved here:

这里有一些可以改进的地方:

  • We are using OptionalView’s implementation instead of using an abstraction. If we need to modify or replace OptionalView, maintaining the same behavior, we will still need to modify every container where it is used.

    我们正在使用OptionalView的实现,而不是使用抽象。 如果我们需要修改或替换OptionalView ,并保持相同的行为,我们仍然需要修改使用它的每个容器。

  • We are maintaining two references for one OptionalView, and we are letting the container(s) know that we are using a factory for the OptionalView. If at some point, OptionalView became not optional, we might want or need to remove the factory method pattern. In that case, we will also need to modify all containers where OptionalView is being used.

    我们为一个OptionalView维护两个引用,并且让容器知道我们正在为OptionalView使用工厂。 如果在某些时候OptionalView变得不是可选的,则我们可能希望或需要删除工厂方法模式。 在这种情况下,我们还需要修改所有使用OptionalView容器。

抽象工厂方法模式 (Abstract Factory Method Pattern)

Using an abstraction for the optional view with the factory method pattern will solve the first issue. Let’s see how:

对带有工厂方法模式的可选视图使用抽象将解决第一个问题。 让我们看看如何:

Image for post
OptionalView with abstract factory method in Swift+UIKit
Swift + UIKit中带有抽象工厂方法的OptionalView
import UIKit


protocol OptionalViewProtocol {
    var view: UIView { get }
    func viewDidLoad()
    func viewWillAppear()
}


class OptionalView: UIView, OptionalViewProtocol {
    var view: UIView { self }
    func viewDidLoad() {}
    func viewWillAppear() {}
}


protocol OptionalViewFactoryProtocol {
    func makeOptionalView() -> OptionalViewProtocol?
}


struct OptionalViewFactory: OptionalViewFactoryProtocol {
    func makeOptionalView() -> OptionalViewProtocol? {
        // Conditions
        return OptionalView()
    }
}


class ContainerViewController: UIViewController {
    let optionalViewFactory: OptionalViewFactoryProtocol
    var optionalView: OptionalViewProtocol?
    
    init(optionalViewFactory: OptionalViewFactoryProtocol) {
        self.optionalViewFactory = optionalViewFactory
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        if let optionalView = optionalViewFactory.makeOptionalView() {
            self.optionalView = optionalView
            view.addSubview(optionalView.view)
            optionalView.viewDidLoad()
        }
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        optionalView?.viewWillAppear()
    }
}

Now we have decoupled the implementation of OptionalView from the Container(s), but we are still exposing that we are using a factory for instantiating the optional view.

现在,我们已经将OptionalView的实现与Container分离开了,但是我们仍然暴露出我们正在使用工厂实例化可选视图。

代理模式 (Proxy Pattern)

Now that we are using an abstraction for OptionalView, it is easier to encapsulate the factory using a proxy pattern so the container does not need to know. Let’s see how:

现在,我们对OptionalView使用了抽象,使用代理模式封装工厂变得更加容易,因此容器不需要知道。 让我们看看如何:

Image for post
OptionalView with Abstract Factory MethodProxy Pattern in Swift+UIKit
Swift + UIKit中带有抽象工厂MethodProxy模式的OptionalView
import UIKit


protocol OptionalViewProtocol {
    var view: UIView? { get }
    func viewDidLoad()
    func viewWillAppear()
}


class OptionalView: UIView, OptionalViewProtocol {
    var view: UIView? { self }
    func viewDidLoad() {}
    func viewWillAppear() {}
}


class OptionalViewProxy: OptionalViewProtocol {
    lazy var optionalView: OptionalView? = {
         // Conditions
         return OptionalView()
    }()
    var view: UIView? { optionalView }
    func viewDidLoad() { optionalView?.viewDidLoad() }
    func viewWillAppear() { optionalView?.viewWillAppear() }
}


class ContainerViewController: UIViewController {
    let optionalView: OptionalViewProtocol
    
    init(optionalView: OptionalViewProtocol) {
        self.optionalView = optionalView
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        if let optionalView = optionalView.view {
            view.addSubview(optionalView)
        }
        optionalView.viewDidLoad()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        optionalView.viewWillAppear()
    }
}




// With Proxy
let proxy = OptionalViewProxy()
let viewControllerWithProxy = ContainerViewController(optionalView: proxy)


// Without Proxy
let view = OptionalView()
let viewControllerWithoutProxy = ContainerViewController(optionalView: view)

Here we are only referencing the abstraction of OptionalView, but we are actually injecting a proxy. This proxy could itself act as a factory method or it could delegate the task in another class.

在这里,我们仅引用OptionalView的抽象,但实际上是在注入代理。 该代理本身可以充当工厂方法,也可以将任务委托给另一个类。

Containers do not know anything about the factory and we could remove the proxy without having to modify any containers at all.

容器对工厂一无所知,我们可以删除代理,而不必修改任何容器。

Thank you for reading. Let me know what you think.

感谢您的阅读。 让我知道你的想法。

翻译自: https://medium.com/better-programming/swift-optional-views-with-the-proxy-and-abstract-factory-patterns-5f24f8cf84b8

工厂模式和抽象工厂模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值