设计模式创建者模式抽象工厂AbstractFactory

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
[[《Design Patterns》]]

The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes.
wiki

关键字为:创建一组有关联的对象,不需要特别指定实体类

Client 为使用代码的角色
Factory 用于生产 XXXProduct
此时客户端编程将面向接口编程,而不是面向实现编程

动态性最差语言的 Java 的实现,这也是设计模式吹比高发区

package org.example;

import org.example.abstractfactory.*;

public class Main {
    public static void main(String[] args) {
        // 在这里修改需要切换的工厂
        WidgetFactory wf = new PMWidgetFactory();
        WidgetFactory wf2 = new MotifWidgetFactory();

        // 使用了此对象创建方法后,之后的代码都不需要改了
        // 问题的关键在于 Client 可能需要灵活使用不同的 Product 组
        ScrollBar scrollBar = wf.CreateScrollBar();
        Window window = wf.CreateWindow();

        scrollBar.setColor("#FF00FF");
        window.setBackgroundImage("./images/bg.jpg");
    }
}

Python 的 OO 实现

from abc import ABC, abstractmethod
from sys import platform

# Products
class Button(ABC):
    @abstractmethod
    def paint(self):
        pass


class LinuxButton(Button):
    def paint(self):
        return "Render a button in a Linux style"


class WindowsButton(Button):
    def paint(self):
        return "Render a button in a Windows style"


class MacOSButton(Button):
    def paint(self):
        return "Render a button in a MacOS style"

# Factory
class GUIFactory(ABC):
    @abstractmethod
    def create_button(self):
        pass


class LinuxFactory(GUIFactory):
    def create_button(self):
        return LinuxButton()


class WindowsFactory(GUIFactory):
    def create_button(self):
        return WindowsButton()


class MacOSFactory(GUIFactory):
    def create_button(self):
        return MacOSButton()

# Client Invoke
if platform == "linux":
    factory = LinuxFactory()
elif platform == "darwin":
    factory = MacOSFactory()
elif platform == "win32":
    factory = WindowsFactory()
else:
    raise NotImplementedError(f"Not implemented for your platform: {platform}")

button = factory.create_button()
result = button.paint()
print(result)

PHP 的 OO 实现

<?php
// Products
interface Button {
	public function paint();
}

class LinuxButton implements Button
{
	public function paint() {
		echo "Render a button in a Linux style";
	}
}
class WindowsButton implements Button
{
	public function paint() {
		echo "Render a button in a Windows style";
	}
}
class MacOSButton implements Button
{
	public function paint() {
		echo "Render a button in a MacOS style";
	}
}

// Factory
interface GUIFactory {
	public function createButton();
}

class LinuxFactory implements GUIFactory
{
	public function createButton() {
		return new LinuxButton();
	}
}

class WindowsFactory implements GUIFactory
{
	public function createButton() {
		return new WindowsButton();
	}
}
class MacOSFactory implements GUIFactory
{
	public function createButton() {
		return new MacOSButton();
	}
}

# Client Invoke
$platform = 'linux';
if ($platform == "linux") {
    $factory = new LinuxFactory();
} else if($platform == "darwin"){
    $factory = new MacOSFactory();
} else if($platform == "win32"){
    $factory = new WindowsFactory();
} else {
	throw new Exception("Not implemented for your platform: {$platform}");
}
    

$button = $factory->createButton();
$result = $button->paint();

PHP 的高阶实现

<?php
// Products
class LinuxButton
{
	public function paint() {
		echo "Render a button in a Linux style";
	}
}

class WindowsButton
{
	public function paint() {
		echo "Render a button in a Windows style";
	}
}

class MacOSButton
{
	public function paint() {
		echo "Render a button in a MacOS style";
	}
}

// Factory: I'm dead

# Client Invoke
// 如何利用动态性将 OO 的抽象工厂“干掉”,当类名可以作为参数进行传递并实例化的时候。
// 此时的 Button interface 仅仅作为一个约定而存在,因为动态语言本身不强制类型静态检查
// 我们可以将方法 paint 放到运行时检查,如此一来我们删减了大量的样板代码,程序更加清晰
// 至于需要面临的问题,留给读者自己思考与解决
// ===================================================
$platform = 'MacOS'; // Linux Windows MacOS
$className = "{$platform}Button";
$button = new $className();
// ===================================================

$result = $button->paint();
posted @ 2022-12-01 01:09  我听不见  阅读(38)  评论(0编辑  收藏  举报