设计模式之简单工厂模式

author author     2022-08-15     742

关键词:

设计模式之简单工厂模式
动机:
        不暴露实例化逻辑来创建对象。通过公共的接口创建新的对象。
        这是一个简单的实现,客户端需要一个product,但是client不直接使用new对象,而是通过提供需要的对象信息来找factory得到新的product。
        这个factory实例化一个具体的product并返回(转化成抽象的类),client段使用这个抽象的类而不用考虑它具体的实现。

应用举例:        也许工厂模式是使用最多的模式之一。举个例子,一个操作图像的图形应用。在我们实现绘画的模块就是client,而那些shapes图形就是products,所有的图形都继承自一个abstract shape抽象的形状类(或者接口)。 这个abstract shape定义了绘画draw和move方法去让子类实现。让我们假设有个创建圆形的命令,client接收一个string类型的图形类型参数,client从factory得到concrete shape转换成abstract shape。
        这样的好处是很显然的:新增一个图形不用修改client的代码,只要在factory的实现里面增加新的类型即可。
详细问题和解决方法:
        新手使用switch/case参数化factory,生成product的方法可以被重写,所以factory可以生成更多类型的product对象,使用一个条件(输入一个方法参数或者一些全局配置参数)头标识哪种product对象应该被创建。代码如下:
public class ProductFactory{
    public Product createProduct(String ProductID){
        if (id==ID1)
            return new OneProduct();
        if (id==ID2) return
            return new AnotherProduct();
        ... // so on for the other Ids
        return null; //if the id doesn‘t have any of the expected values
    }
    ...
}
        这种实现方法是简单直接的(让我们称之为新手实现),这里的问题就是,新增一种product我们就要修改factory类,不够弹性,违反了开闭原则。当然我们可以继承factory类,但是别忘了factory类通常是单例的。
注册类-使用反射reflection:
        如果你可以使用反射,就可以在不修改factory的前提下注册新的product类。在不知道product类型的前提下我们在facoty中创建product对象,我们可使用map保存productID和product type,在这种情况下,新增一个新的product,需要在map中注册该product,这个操作不需要修改factory的代码:
class ProductFactory
{
    private HashMap m_RegisteredProducts = new HashMap();
    public void registerProduct (String productID, Class productClass)
    {
        m_RegisteredProducts.put(productID, productClass);
    }
    public Product createProduct(String productID)
    {
        Class productClass = (Class)m_RegisteredProducts.get(productID);
        Constructor productConstructor = cClass.getDeclaredConstructor(new Class[] { String.class });
        return (Product)productConstructor.newInstance(new Object[] { });
    }
}
        我们可以把registion code注册代码放在任何地方,但是使用static静态代码块在product类里面注册是一个方便的方法,看下面的例子:
1、在product类外面注册:
public static void main(String args[]){
        Factory.instance().registerProduct("ID1", OneProduct.class);
    } 
2、在product类里面注册:
class OneProduct extends Product
{
	static {
		Factory.instance().registerProduct("ID1",OneProduct.class);
	}
	...
}        我们必须确保在factroy使用concrete product具体的product之前完成注册,不然就会出现null point空指针,我们在Main类的static静态代码块中使用Class.forName方法。Class.forName方法支持返回一个类的实例,如果一个编译器没有加载这个类,编译器就会在Class.forName被调用的时候加载。
class Main
{
    static
    {
        try
        {
            Class.forName("OneProduct");
            Class.forName("AnotherProduct");
        }
        catch (ClassNotFoundException any)
        {
            any.printStackTrace();
        }
    }
    public static void main(String args[]) throws PhoneCallNotRegisteredException
    {
        ...
    }
}
        这种反射实现有它的坏处,一个主要的坏处就是它的性能表现,使用反射要比不使用反射性能表现降低10%。
注册类-不使用反射:
        在之前的段落中我们看到facotory使用map保存productID和product type,这个注册器在factory外面实现,因为通过使用反射不用再关心所要创建对象的类型。
        我们不想使用反射,但是同时factory又不需要考虑product类型。我们在product abstract class里面新增一个新的abstract方法,每个具体的类都要实现设个方法去创造自己。我们也不得不改变注册器这样我们将注册具体的product对象。
abstract class Product
{
    public abstract Product createProduct();
    ...
}
class OneProduct extends Product
{
    ...
    static
    {
        ProductFactory.instance().registerProduct("ID1", new OneProduct());
    }
    public OneProduct createProduct()
    {
        return new OneProduct();
    }
    ...
}
class ProductFactory
{
    public void registerProduct(String productID, Product p)    {
        m_RegisteredProducts.put(productID, p);
    }
    public Product createProduct(String productID){
        ((Product)m_RegisteredProducts.get(productID)).createProduct();
    }
}
一个更高级的解决方法-使用抽象工厂abstract factory(工厂方法 factory method):
    这种实现代表一个可修改的注册器类实现,假设我们新增一个新的product,使用过程化的switch/case我们需要修改factory类的代码,而使用注册器类,我们要做的只是把注册器类给factory,而不用修改factory,这肯定是一个弹性的解决方式。
    过程化的实现方式是典型的违背开闭原则的坏例子,我们能看到有很多扩展factory的直接解决方法去避免修改factory。
工厂方法模式factory method pattern经典的实现方式有一些坏处通过注册器,而没有很多的好处:
 好处:当product对象被创建的时候,继承的factory method可以被修改去表现添加的操作。
坏处:
    1、factory必须要用singleton实现。
    2、每个factory必须要在使用前先实例化。
    3、实现起来有更多的困难。
    4、如果一个新的product要被创建,一个新的factory要被创建。
不管怎么样,经典的实现方式有它的好处,可以帮助我们理解抽象工厂模式abstract factory pattern。
结论:        当你设计一个应用的时候,考虑你是否需要使用factory,也许使用factory会带来没必要的复杂。如果你有很多类有相同的基本类型,你就需要使用factory,如果你有许多如下的代码,你就要重新考虑:
(if (ConcreteProduct)genericProduct typeof )
    ((ConcreteProduct)genericProduct).doSomeConcreteOperation().
        如果你决定使用factory模式,我会推荐你使用带注册器的实现(使用反射或者不使用反射都行),避免使用factory method,记住switch/case是最简单,违反开闭原则,只是用来解释factory原理的。


本文出自 “不死的小强” 博客,请务必保留此出处http://qianray.blog.51cto.com/4607992/1878313

设计模式之工厂方法模式

一、引言  在简单工厂模式中讲到简单工厂模式的缺点,有一点是——简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过于复杂,工厂方法模式可以解决简单工厂模... 查看详情

设计模式之工厂模式-简单工厂(02)

设计模式分创建型、行为型、结构型;工厂模式属于创建型模式,分(1)简单工厂(静态工厂)(2)工厂方法(3)抽象工厂,下面分别通过代码来介绍(本篇文章北风网的视频看后写的);(一)简单工厂  简单工厂描述:... 查看详情

工厂模式之简单工厂模式

  简单工厂模式(静态工厂方法模式)就是由一个工厂类根据传入的参量决定创建出哪一种产品类的实例。其结构如下图所示:          简单工厂模式涉及到工厂角色、抽象产品角色和具体产品角色。   &nb... 查看详情

简单工厂模式的强大之处

...知道每次要实例化哪一个类。工厂模式有以下几种形态:简单工厂(SimpleFactory)模式工厂方法(FactoryMethod)模式抽象工厂(AbstractFactory)模式 一、 简单工厂(SimpleFactory)模式SimpleFactory模式根据提供给它的数据,返回... 查看详情

设计模式之简单工厂模式(代码片段)

简单来说,工厂模式就是按照需求来返回一个类型的对象,使用工厂模式的意义就是,如果对象的实例化与代码依赖太大的话,不方便进行扩展和维护,使用工厂的目的就是使对象的实例化与主程序代码就行解耦.1.简单工厂模式简介简... 查看详情

设计模式从青铜到王者第五篇:创建型模式之简单工厂模式(simplefactorypattern)(代码片段)

系列文章目录文章目录系列文章目录前言一、简单工厂模式模式动机二、简单工厂模式模式定义三、简单工厂模式模式结构四、简单工厂模式时序图五、简单工厂模式代码分析六、简单工厂模式模式分析七、简单工厂模式优点八... 查看详情

设计模式之简单工厂模式

简单工厂模式实现计算器功能:usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespace简单工厂模式{classProgram{staticvoidMain(string[]args){Operationoperation=Ope 查看详情

设计模式之简单工厂模式

简单工厂模式实现计算器功能:usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespace简单工厂模式{classProgram{staticvoidMain(string[]args){Operationoperation=Ope 查看详情

设计模式之简单工厂模式(代码片段)

引言   所属:创建型模式,常用设计模式之一  工厂模式分为:简单工厂模式、工厂方法模式、静态工厂模式、抽象工厂模式。  下面为简单工厂模式。 工厂模式概述   通过使用一个公共接口来指向不同方... 查看详情

设计模式之简单工厂模式

优点,是灵活应对变化,降低程序的耦合性。缺点,增加算法,都要修改对应的工厂类。  查看详情

gof23种设计模式之简单工厂模式工厂方法模式和抽象工厂模式

查看详情

工厂模式之简单工厂模式

简单工厂模式简介工厂模式有一种非常形象的描述,建立对象的类就如一个工厂,而需要被建立的对象就是一个个产品;在工厂中加工产品,使用产品的人,不用在乎产品是如何生产出来的。从软件开发的角度来说,这样就有效... 查看详情

设计模式之简单工厂模式(代码片段)

简单画图理解//设计模式之简单工厂模式//创建一个食物类interfaceFoodvoideat();//我今天想吃薯条或汉堡classHamburgerimplementsFood@Overridepublicvoideat()System.out.println("我吃汉堡");classFrenchFriesimplementsFood@Overridepublicvoidea 查看详情

设计模式之简单工厂模式

概念  应用场景  一个类多个子类,也就是多态的情况,当我们 代码示例 查看详情

设计模式之简单工厂模式

设计模式之简单工厂模式(—)    设计模式是指在代码在一定程度上降低耦合度,使得代码看起来不是特别繁琐,他们之间的联系性更小,使得在后期代码的维护上大大提高了效率,  所以设计模式的研究对于一个程序... 查看详情

设计模式之简单工厂模式(代码片段)

2018-09-16 23:50:57简单工厂模式概述  简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。    UML类图如下:     该模式中包含的角色及其职责(摘自:百度百科)   工厂(Creator)角色 ... 查看详情

设计模式之工厂模式

工厂模式分为三大类简单工厂(SimpleFactory)工厂方法模式(FactoryMethod)抽象工厂模式(AbstractFactory)动态工厂(DynamicFactory。属于优化版简单工厂)目的:    工厂模式主要是为创建对象提供过渡接口。以便将创建对... 查看详情

设计模式之简单工厂模式(创建型)(代码片段)

定义简单工厂模式又称静态工厂模式。可以根据参数的不同返回不同类的实例。定义一个类来创建其它类的实例。角色简单工厂模式包含如下角色Factory:工厂角色Product:抽象产品角色ConcreteProduct:具体产品角色简单实例publicabst... 查看详情