工厂模式

倖福魔咒の 提交于 2020-03-19 14:57:44

3 月,跳不动了?>>>

简单工厂

简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫静态工厂方法模式(Static FactoryMethod Pattern),是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。不属于GOF 23种设计模式。

优点:解耦,简单工厂适用于工厂类负责创建对象较少的场景;客户只需要传入工厂类的参数,对于如何创建类的逻辑不需要关系。

缺点:工厂类的职责过重,不易于扩展过于复杂的产品结构。

例子:

public interface ISimple {
    
    void output();
}

public class SimpleA implements ISimple{
    @Override
    public void output() {
        System.out.println("输出:SimpleA");
    }
}
public class SimpleB implements ISimple{
    @Override
    public void output() {
        System.out.println("输出:SimpleB");  
    }
}
public class SimpleFactory {
    
    public ISimple outputObject(Class<? extends ISimple> clazz){
        try {
            return clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
public class Test {
    public static void main(String [] args){
        SimpleFactory simpleFactory=new SimpleFactory();
        ISimple simple = simpleFactory.outputObject(SimpleB.class);
        simple.output();
    }
}
输出:SimpleB

类图:

源码例子:

JDK源码例子:
类:java.util.Calendar
方法:private static Calendar createCalendar(TimeZone zone,Locale aLocale){
        CalendarProvider provider =
            LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                                 .getCalendarProvider();
        if (provider != null) {
            try {
                return provider.getInstance(zone, aLocale);
            } catch (IllegalArgumentException iae) {
                // fall back to the default instantiation
            }
        }

        Calendar cal = null;
        if (aLocale.hasExtensions()) {
            String caltype = aLocale.getUnicodeLocaleType("ca");
            if (caltype != null) {
                //使用简单工厂获取对象
                switch (caltype) {
                case "buddhist":
                cal = new BuddhistCalendar(zone, aLocale);
                    break;
                case "japanese":
                    cal = new JapaneseImperialCalendar(zone, aLocale);
                    break;
                case "gregory":
                    cal = new GregorianCalendar(zone, aLocale);
                    break;
                }
            }
        }
        if (cal == null) {
            if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                cal = new BuddhistCalendar(zone, aLocale);
            } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                       && aLocale.getCountry() == "JP") {
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else {
                cal = new GregorianCalendar(zone, aLocale);
            }
        }
        return cal;
    }
日志源码例子:
类:org.slf4j.LoggerFactory
private Logger logger = LoggerFactory.getLogger(getClass());
  public static Logger getLogger(String name) {
    ILoggerFactory iLoggerFactory = getILoggerFactory();
    return iLoggerFactory.getLogger(name);
  }


工厂方法模式

工厂方法模式(Factory Method)是指定义一个创建对象的接口;让实现这个接口的类来决定实例化那个类,工厂方法让类的实例化推迟到子类进行,在工厂方法模式中用户只需关心所需产品对应的工厂,无需关心创建细节,而且加入新的产品符合开闭原则。工厂方法模式主要解决产品扩展问题,在简单工厂中;随着产品链的丰富,如果每个创建对象逻辑有区分的话。工厂职责会变得越来越多,有点像万能工厂。不易维护。根据单一职责原则将职能继续拆分;专人干专事。

优点:客户端不依赖产品类实例如何被创建、实现等细节。一个类通过其子类来指定创建那个对象。

缺点:累的个数增多;增加系统复杂度。增加了系统的抽象性和理解难度。

例子:

public interface ISimpleFactory {
    
    public ISimple create();
}
public class SimpleAFactory implements ISimpleFactory{
    @Override
    public ISimple create() {
        return new SimpleA();
    }
}
public class SimpleBFactory implements ISimpleFactory{
    @Override
    public ISimple create() {
        return new SimpleB();
    }
}
public class Test {
    public static void main(String [] args){
        ISimpleFactory simpleFactory=new SimpleAFactory();
        ISimple iSimple = simpleFactory.create();
        iSimple.output();
    }
}
输出:SimpleA

类图:

抽象工厂

抽象工厂模式(Abstract Factory Pattern) 是指提供一个创建一系列相关或相互依赖对象的接口。无需指定他们具体的类。客户端不依赖于产品类实例如何被创建、实现等细节。强调的是一系列相关产品对象(属于同一产品族)一起使用创建对象需大量重复的代码。需要提供一个产品类的库;所有产品以同意的接口出现,而是客户端不依赖于具体实现

从上图中我们看到面包、薯条、可乐3种零食。相同零食代表一个产品族。麦当劳、I mlovein it卖的面包、薯条、可乐代表产品等级结构。

代码例子:

//定义产品等级
public interface IBread {
    
    //生产面包
    void produce();
}
public interface ICola {
    //生产可乐
    void produce();
}
public interface IFrenchFries {
    //生产薯条
    void produce();
}
public class Bread implements IBread{
    @Override
    public void produce() {
        System.out.println("选择面包");
    }
}
public class Cola implements ICola{
    @Override
    public void produce() {
        System.out.println("选择可乐");
    }
}
public class FrenchFries implements IFrenchFries {
    @Override
    public void produce() {
        System.out.println("选择薯条");
    }
}
//定义抽象工厂
public abstract class ProduceFactory {
    public void init(){
        System.out.println("初始化数据");
    }
    
    protected abstract IBread createBread();
    
    protected abstract ICola createCola();
    
    protected abstract IFrenchFries createFrenchFries();
}
//定义产品族
//I M Love It具体实现工厂
public class IMLoveItFactory extends ProduceFactory{
    @Override
    protected IBread createBread() {
        super.init();
        return new Bread();
    }
    
    @Override
    protected ICola createCola() {
        return new Cola();
    }
    
    @Override
    protected IFrenchFries createFrenchFries() {
        return new FrenchFries();
    }
}
//麦当劳具体实现工厂
public class McDonaldsFactory extends ProduceFactory{
    
    
    @Override
    protected IBread createBread() {
        return new Bread();
    }
    
    @Override
    protected ICola createCola() {
        return new Cola();
    }
    
    @Override
    protected IFrenchFries createFrenchFries() {
        return new FrenchFries();
    }
}
public class Test {
    public static void main(String [] args){
        System.out.println("麦当劳生产------------------");
        ProduceFactory mcDonaldsFactory=new McDonaldsFactory();
        mcDonaldsFactory.createBread().produce();
        mcDonaldsFactory.createCola().produce();
        mcDonaldsFactory.createFrenchFries().produce();
    
        System.out.println("I M Love It生产------------------");
        ProduceFactory imLoveItFactory=new IMLoveItFactory();
        imLoveItFactory.createBread().produce();
        imLoveItFactory.createCola().produce();
        imLoveItFactory.createFrenchFries().produce();
        
    }
}

输出:
麦当劳生产------------------
选择面包
选择可乐
选择薯条
I M Love It生产------------------
初始化数据
选择面包
选择可乐
选择薯条

类图:

优点:

1、最大的好处便是易于交换产品系列,由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同产品配置。

2、它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操作实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。

缺点:

1、规定了所有可能被创建的产品集合、产品族扩展新的产品困难,需要修改抽象工厂的接口。

2、增加了系统的抽象性和理解难度

总结:在实际需求中产品等级结构升级是非常正常的事情。我们可以根据实际情况,只要不是频繁升级,可以不遵循开闭原则。代码每半年升级一次或每年升级一次又有何不可呢。

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