浅谈abstractfactory抽象工厂模式

丶灬走出姿态 提交于 2019-11-30 13:04:47

一、前言

上次我们学习了Builder模式,用来组装复杂的实例,Builder就是我们盖房子的一块块砖头,钢筋和水泥,以及简单的用法,使用监工将这些元素有机的组合在了一起就能够建造整个建筑了,是监工将这些原材料按照一定的次序和特定的处理流程糅合在一起,这个过程就是组装。而现在我们学习了抽象工厂模式,将关键零件组装成产品。

在此之前,让我们对前面的几种模式做简单的回顾,首先我们学习了迭代器模式,使用了工厂方法创造迭代器,并且完成了元素的内部实现和遍历的分离,因此成为“器”,也算是一种配合,其次我们学习了适配器,有类适配器和对象适配器,这两者只是实现的方式不同,本质是一样的,都是通过在原素材上加入一个适配器使得能够满足现在的需要,一般用在版本之间的兼容上使得新版本的内容能够在旧版本上使用(适配),以及一些复用的时候需要适当的修改(适配)的场合;之后我们学习了模板模式和工厂模式,模板方法的一个特殊实现其实就是工厂方法,模板方法就是通过在父类之中定义职责,然后让子类实现各自的子任务,最后通过父类进行调用,提高了代码的可修改性和可扩展性,工厂方法则是在模板方法的基础上,通过生产产品的方式将框架的实现分离,遵循了高内聚低耦合的原则;在之后我们学习了单例模式和原型模式,单例模式是保证全局关于某个类只有一个对象,在某些多线程或者编码误用的条件下非常重要,原型模式则是实现了对象的深浅拷贝,使得经过了很长时间才得到的对象能够保存以及复制和使用,省去了很多不必要的new操作。之后我们学习了Builder模式,通过增加一个监工类来将父类中定义的方法组合起来实现某种功能,实现了类的隔离,便于代码的复用,是模板模式的升级版。

学习了这么多模式,不知道大家对设计模式有没有什么感悟,可以说就是通过接口、抽象类。继承、多态等机制遵循高内聚低耦合、封闭原则、里式代换原则等实现代码的可复用性,可扩展性,尽管比以前变得复杂了,其实成都越大扩展就越简单。那么为什么又是抽象工厂模式呢?

抽象工厂模式是一个非常复杂的模式,和工厂方法键值差别太大了,但是也有相同之处,那就是抽象工厂也是用了工厂方法来创造产品,只不过抽象工厂模式中包含了零件、产品、工厂、抽象等概念,这样就非常的复杂了,一般还要用到模板方法、迭代器甚至原型模板等,就“抽象”两个字来说,就是将所有的角色分成两部分,一部分是这个角色的抽象类,另一部分是这个角色的实现类,工厂就是沿用了工厂模式,因此抽象工厂模式分为两大部分,抽象部分和具体实现部分,如图所示:

上面的抽象部分,最重要的就是抽象的工厂类(Link)、抽象的零件类(Tray)、抽象的产品类(Page),这两个零件有共同之处,因此通过item类进行抽象便于两者之间的互通。下面的具体实现部分即使对抽象的实现了,之后我们使用main类来进行整合,可以发现我们只用对抽象类进行编程,完全不用使用任何的具体类就能实现我们想要的功能,甚至导致编译器在编译的时候还需要指出需要编译的具体类,因为我们使用了Class.forName()方法实现了反射。这样的结构看似非常的庞大,其实仔细的推敲,反而妙趣横生,当我们还想创建一个具体的工厂的时候实在是太简单了,原来抽象工厂的代码都不用修改,只用按照响应的抽象实现就可以了,之后我们就可以直接使用了,只用在main中将Class.forName()所指定的类改一下就可以了,非常的方便。凡是有利就有弊,如果我们对抽象工厂中的某些定义不满意了呢,这个时候如果我们对抽象方法进行一定的调整和更改(增加或删除),那么所有实现了该抽象工厂的具体工厂的类都需要进行修改,如果有100个具体工厂,无疑是非常可怕的,因此我们应该理智的取舍,废话少说,让我们看一下代码。

二、代码实现

我们将类分成三个部分,这样思路更加清晰,第一部分是抽象工厂中的类,第二部分是具体实现的具体工厂类,第三部分是测试使用的Main类。

抽象工厂包:

 Item 抽象类:

package designMode.abstractfactory.factory;

public abstract class Item {
    protected String caption;
    public Item(String caption){
        this.caption=caption;
    }
    public abstract String makeHTML();
}

 Link抽象类:

package designMode.abstractfactory.factory;

public abstract class Link extends  Item{
    public String url;
    public Link(String caption,String url) {
        super(caption);
        this.url = url;
    }
}

 Tray抽象类:

package designMode.abstractfactory.factory;

import java.util.ArrayList;

public class Tray extends Item {
    protected ArrayList items = new ArrayList();
    public Tray(String caption) {
        super(caption);
    }

    @Override
    public String makeHTML() {
        return null;
    }

    public void add(Item item){
        items.add(item);
    }
}

Page抽象类: 

package designMode.abstractfactory.factory;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;

public abstract class Page {
    protected String title;
    protected String author;
    protected ArrayList content = new ArrayList();

    public Page(String title,String author) {
        this.author = author;
        this.title=title;
    }

    public void add(Item item){
        content.add(item);
    }

    public void output(){
        String filename = title + ".html";
        try {
            Writer writer = new FileWriter(filename);
            writer.write(this.makeHTML());
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("写入文件:"+filename+"已成功!");
    }
    public abstract String makeHTML() ;
}

Factory工厂抽象类: 

package designMode.abstractfactory.factory;

//Factory工厂抽象类:
public abstract class Factory {
    public static Factory getFactory(String classname){
        Factory factory = null;
        try {
            factory = (Factory) Class.forName(classname).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return factory;
    }
    public abstract Link createLink(String caption,String url);
    public abstract Tray createTray(String caption);
    public abstract Page createPage(String title,String author);
}

具体实现工厂类:

ListLink类:

package designMode.abstractfactory.listfactory;

import designMode.abstractfactory.factory.Link;

public class ListLink extends Link {
    public ListLink(String caption, String url) {
        super(caption, url);
    }

    @Override
    public String makeHTML() {
        return "<li>"+"<a href=\""+url+"\" >"+caption+"</a></li>\n";
    }
}

 ListTray类:(迭代器模式)ArrayList本身实现了迭代器。 

package designMode.abstractfactory.listfactory;

import designMode.abstractfactory.factory.Item;
import designMode.abstractfactory.factory.Tray;

import java.util.Iterator;

public class ListTray extends Tray {
    public ListTray(String caption) {
        super(caption);
    }

    public String makeHTML() {
        StringBuffer sb=new StringBuffer();
        sb.append("<li>\n");
        sb.append(caption+"\n");
        sb.append("<ul>\n");

        Iterator it=items.iterator();
        while(it.hasNext()){
            Item item=(Item)it.next();
            sb.append(item.makeHTML());
        }
        sb.append("</ul>\n");
        sb.append("</li>\n");
        return sb.toString();
    }
}

 ListPage类:(迭代器模式)ArrayList本身实现了迭代器。

package designMode.abstractfactory.listfactory;

import designMode.abstractfactory.factory.Item;
import designMode.abstractfactory.factory.Page;

import java.util.Iterator;

public class ListPage extends Page {
    public ListPage(String title, String autor) {
        super(title, autor);
    }

    @Override
    public String makeHTML() {
        StringBuffer sb=new StringBuffer();
        sb.append("<html><head><title>"+title+"</title></head>");
        sb.append("<body>\n");
        sb.append("<h1>"+title+"</h1>");

        sb.append("<ul>\n");
        Iterator it=content.iterator();
        while(it.hasNext()){
            Item item=(Item)it.next();
            sb.append(item.makeHTML());
        }
        sb.append("</ul>\n");
        sb.append("<hr><address>"+author+"</address>");
        sb.append("</body></html>\n");
        return sb.toString();
    }
}

ListFactory类:(工厂方法模式)

package designMode.abstractfactory.listfactory;

import designMode.abstractfactory.factory.Factory;
import designMode.abstractfactory.factory.Link;
import designMode.abstractfactory.factory.Page;
import designMode.abstractfactory.factory.Tray;

public class ListFactory extends Factory {
    @Override
    public Link createLink(String caption, String url) {
        return new ListLink(caption,url);
    }

    @Override
    public Tray createTray(String caption) {
        return new ListTray(caption);
    }

    @Override
    public Page createPage(String title, String author) {
        return new ListPage(title,author);
    }
}

 Main类:

package designMode.abstractfactory.test;

import designMode.abstractfactory.factory.Factory;
import designMode.abstractfactory.factory.Link;
import designMode.abstractfactory.factory.Page;
import designMode.abstractfactory.factory.Tray;

public class Main {
    public static void main(String[] args) {
        String[] choice = {"designMode.abstractfactory.listfactory.listFactory.ListFactory"};
        Factory factory = Factory.getFactory(choice[0]);

        Tray tray_life=factory.createTray("我的生活");
        Link link_graduate=factory.createLink("我的本科", "http://www.swjtu.edu.cn");
        Link link_postgraduate=factory.createLink("我的研究生","http://www.uestc.edu.cn");
        tray_life.add(link_graduate);
        tray_life.add(link_postgraduate);
        Tray tray_blog=factory.createTray("我的博客");
        Link link_iterator=factory.createLink("迭代器","https://www.cnblogs.com/zyrblog/p/9217673.html");
        Link link_adapter=factory.createLink("适配器", "https://www.cnblogs.com/zyrblog/p/9218316.html");
        tray_blog.add(link_iterator);
        tray_blog.add(link_adapter);
        Tray tray_blog_all=factory.createTray("博客园");
        Link link_other1=factory.createLink("解释器模式", "https://www.cnblogs.com/Answer-Geng/p/9231042.html");
        Link link_other2=factory.createLink("OAuth 2.0", "https://www.cnblogs.com/cjsblog/p/9230990.html");

        tray_blog_all.add(tray_blog);
        tray_blog_all.add(link_other1);
        tray_blog_all.add(link_other2);

        Page page=factory.createPage("zyr", "朱彦荣");

        page.add(tray_life);
        page.add(tray_blog_all);

        page.output();
    }
}

可以看到完全组成了一个网页。看到这里大家可能很质疑,难道废了这么大的功夫就是为了实现这么简单的功能?其实这里我们可以看到抽象工厂的强大之处,零件的组装与嵌套,相互关联,通过迭代器、模板模式、工厂模式等最终实现了这种功能,可扩展性非常强大,如果还要生成其它种类的工厂,将非常的方便,直接写实现类就可以了,其它代码基本不需要改动,这样的功能可以说非常强大了,至今为止我们很多的代码都是强耦合的,很难实现复用,而这个抽象的工厂模式就可以实现高层次的复用,只需要知道实现类的类名就可以执行了,我们完全可以实现其他工厂,从而实现其他的功能。抽象工厂模式最重要的就是可复用性和完美的隔离性,其中使用了makeHTML()很多次,通过迭代器来展现了这个方法的多台。灵活使用抽象工厂模式可以说是设计模式真正入门的起点。抽象工厂将抽象零件组装成抽象产品,易于增加具体的工厂难于增加新的零件。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!