zoukankan      html  css  js  c++  java
  • 抽象工厂模式

    2018年8月24日17:20:30

    抽象工厂模式

    定义

    借我一只晨光的铅笔,明天就还给你。

    现在我可以还你晨光的铅笔了,你早已不在了,明天还是明天。

    抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。——《设计模式:可复用面向对象软件的基础》

    使用场景

    首先要来认识两个新概念:产品族产品等级结构

    产品族,是指不同产品等级结构中,功能相关的产品组成的家族。

    产品等级结构, 即产品的继承结构,继承(或实现)同一抽象产品的具体产品属于同一产品等级结构。

    在后面的代码示例中,晨光文具和真彩文具是两个产品族,继承(或实现)铅笔抽象产品的晨光铅笔和真彩铅笔是一个产品等级结构,继承(或实现)橡皮抽象产品的晨光铅笔和真彩铅笔是另一个产品等级结构。【这个我用了继承(或实现)是因为Java中有接口是实现的,抽象类是继承的,抽象产品既可以是接口,也可以是抽象类,为了不误导我自己,特意加上。】例子还有:Intel的主板、芯片组、CPU是一个产品族,AMD的主板、芯片组、CPU也是一个产品族,而这里有三个产品等级结构,分别是:主板、芯片组、CPU。

    想代码示例的时候,想我们经常用的东西,就想到了文具,想到了晨光和真彩。查了一下,没想到小小文具,营业额超十亿。

    现在我们的目标是先赚他一个亿,开一家博客园文具(产品族),产品等级结构呢,他们都有,我们直接继承(或实现)他们的抽象产品类就好了,多方便。这就是抽象工厂模式的好处。增加一个产品族,不用破坏原来代码结构,符合开闭原则。

    但是只有老产品,没有什么竞争力,要不我们增加一个新产品即新的产品等级结构,暂时就是码农作弊专用智能笔,帮你轻松应对笔试,这时我们就要在博客园文具(产品族)添加新成员,需要在博客园文具具体工厂类中添加相关创建新产品的代码,不符合开闭原则。这就是抽象工厂模式的缺点了。

    综上所述,结合其他情况,以下情况可以使用抽象工厂模式:

    1、一个系统不应当依赖于产品实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。

    2、系统有多于一个的产品,且每次只使用其中一个产品族。

    3、属于同一产品族的产品将在一起使用,这一约束应该在系统设计中体现出来。

    4、所有产品以自己继承(或实现)的接口出现,从而客户端不依赖于具体实现。

    第1点,毋庸置疑。第2点和第3点,说的是我选择晨光文具,我使用的就是晨光的铅笔就要使用晨光的橡皮,要配套使用,不能是我使用了晨光的铅笔却使用真彩的橡皮。这个约束在这个例子看起来有点牵强,但是想一下这样的场景:期末考试要同一文具,有两种选择,一种是晨光,一种是真彩,他们是配套的,晨光的铅笔配晨光的橡皮,真彩的铅笔配真彩的橡皮,这样就舒服了。第4点,面向接口编程,降低耦合。

    第2点和第3点,用上面提到的Intel、AMD产品族更贴切,Intel的CPU是无法和AMD的主板匹配的,AMD的CPU也无法和Intel的主板匹配,所以组装电脑的时候,就默认有这个约束:只能使用同一个产品族中的产品。

    关于抽象工厂模式的起源,是用于创建分属于不同操作系统的视窗构建。比如:命令按键(Button)与文字框(Text)都是视窗构建,在UNIX操作系统的视窗环境和Windows操作系统的视窗环境中,这两个构建有不同的本地实现,它们的细节有所不同。视窗构建时,只能选择一个操作系统的Button和Text,如果不是,两个操作系统都用不了,我要这视窗有何用?

    角色

    抽象工厂角色(Abstract Factory):具体工厂(产品族)公共接口

    具体工厂角色(Concrete Factory):产品族

    抽象产品角色(Abstract Product):产品等级结构

    具体产品角色(Concrete Product):产品

    图示

    抽象工厂模式结构图

    代码示例

    代码示例类依赖关系图:

    抽象工厂模式类依赖关系图

    抽象工厂角色(AbstractFactory.java)

    public interface AbstractFactory {
    	public Pencil createPencil();
    	public Eraser createEraser();
    }
    

    具体工厂角色(ChenGuangFactory.java、TrueColorFactory.java)

    // 晨光工厂
    public class ChenGuangFactory implements AbstractFactory {
    
    	@Override
    	public Pencil createPencil() {
    		return new ChenGuangPencil();
    	}
    
    	@Override
    	public Eraser createEraser() {
    		return new ChenGuangEraser();
    	}
    
    }
    // 真彩工厂
    public class TrueColorFactory implements AbstractFactory{
    
    	@Override
    	public Pencil createPencil() {
    		return new TrueColorPencil();
    	}
    
    	@Override
    	public Eraser createEraser() {
    		return new TrueColorEraser();
    	}
    
    }
    

    抽象产品角色(Pencil.java、Eraser.java)

    // 铅笔
    public interface Pencil {
    	public void draw();
    }
    // 橡皮
    public interface Eraser {
    	public void erase();
    }
    

    具体产品角色(ChenGuangPencil.java、TrueColorPencil.java、ChenGuangEraser.java、TrueColorEraser.java)

    // 晨光铅笔
    public class ChenGuangPencil implements Pencil {
    
    	@Override
    	public void draw() {
    		System.out.println("用晨光铅笔画图。");
    	}
    
    }
    // 真彩铅笔
    public class TrueColorPencil implements Pencil {
    
    	@Override
    	public void draw() {
    		System.out.println("用真彩铅笔画图。");
    	}
    
    }
    
    // 晨光橡皮
    public class ChenGuangEraser implements Eraser {
    
    	@Override
    	public void erase() {
    		System.out.println("用晨光橡皮擦除晨光铅笔画的图。");
    	}
    
    }
    // 真彩橡皮
    public class TrueColorEraser implements Eraser {
    
    	@Override
    	public void erase() {
    		System.out.println("用真彩橡皮擦除真彩铅笔画的图。");
    	}
    
    }
    

    测试类(AbstractFactoryTest.java)

    public class AbstractFactoryTest {
    
    	public static void main(String[] args) {
    		// 1、晨光
    		AbstractFactory factory = new ChenGuangFactory();
    		Pencil pencil = factory.createPencil();
    		pencil.draw(); // 用晨光铅笔画图。
    		Eraser eraser = factory.createEraser();
    		eraser.erase(); // 用晨光橡皮擦除晨光铅笔画的图。
    		
    		// 2、真彩
    		AbstractFactory factoryT = new TrueColorFactory();
    		Pencil pencilT = factoryT.createPencil();
    		pencilT.draw(); // 用真彩铅笔画图。
    		Eraser eraserT = factoryT.createEraser();
    		eraserT.erase(); // 用真彩橡皮擦除真彩铅笔画的图。
    	}
    
    }
    

    测试结果:

    抽象工厂模式测试结果图

    优点

    1、拥有简单工厂模式、工厂方法模式一样的优点:客户端不需要知道对象被创建的细节

    2、当产品族中多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的产品。

    3、增加产品族,符合开闭原则。

    缺点

    1、增加产品等级结构时,不符合开闭原则。

    总结

    抽象工厂模式在工厂方法模式的基础上,增添了产品族产品等级结构的概念,以及只使用同一个产品族中的约束,使得抽象工厂模式符合现实生活中的某些场景,成为实用的设计模式,再加上抽象工厂模式实现高内聚低耦合,也为其广泛应用提供基础。

    (给晨光和真彩做广告,是不是应该收点广告费???)

    参考:

    《JAVA与模式》之抽象工厂模式

    2018年8月25日18:31:58

  • 相关阅读:
    寒露将至,略有所感:过河卒 DP入门
    linux 内核中EXPORT_SYMBOL()分析与实践
    Educational Codeforces Round 116 (Rated for Div. 2)
    Educational Codeforces Round 115 (Rated for Div. 2)
    学习笔记:UML类图
    论文阅读笔记Fully Functional Image Manipulation Using Scene Graphs in A Bounding-Box Free Way
    图像质量评价(六)主观评价 subjective ?还没写完
    image manipulation综述
    论文阅读笔记stargan
    10.14-11.7第一轮文献调研内容
  • 原文地址:https://www.cnblogs.com/mingmingcome/p/9534978.html
Copyright © 2011-2022 走看看