设计模式之工厂模式(一)

来源:互联网 发布:spring ioc 源码 编辑:程序博客网 时间:2024/04/28 03:52

    对于对象的创建,当然我们可以直接使用new关键字创造一个新的实例化对象,然而我们也知道,当我们实例化的时候创建活动,不应该总是公开的进行,好比如,我们不能在客户端看到其它的实例化对象,再者,这样的代码会经常性的耦合,代码绑着具体的类会导致代码更加的脆弱,缺乏弹性。在初始化的时候,这样的耦合也不是我们想看到的,是吧,所以我们可以通过工厂模式,由工厂类来集中的管理实例化的对象,这样就可以减少实例化对象创建的时候的耦合。

    下面我们结合一个简单的实例来介绍工厂模式:

1.背景,假如我们开了一家面包店,面包店作为面包店的主人呢我们一直稳定的经营,我们拥有自己的软件点餐系统,我们的点餐系统的某些代码如下:

Cookies orderCookeisStore(){Cookies cookies = new Cookies();cookies.prepare();//准备材料cookies.bake();//烘焙cookies.box();//装盒return cookies;}
   当然呢,我们希望为了使这个系统更有弹性,发生改变的是饼干的创建部分,而制作过程是相同的不变的,所以我们希望Cookies是一个抽象类或者是接口,但是这样就不能直接实例化Cookies了。

所以呢,需要修改代码,将Cookies设置为一个抽象类,让其它类型的Cookies都继承这个抽象类,这样就可以实现我们的期望了,同时,我们在orderCookies()方法代码中需要加入一个判断,使用String类型的type来作为参数进行选择:

Cookies orderCookeis(String type){Cookies cookies ;if("cheese".equals(type)){Cookies = new CheeseCookies();}if("greek".equals(type)){Cookies = new GreekCookies();}if("pepperoni".equals(type)){Cookies = new PepperoniCookies();}cookies.prepare();cookies.bake();cookies.box();return cookies;}
    这样看起来似乎是解决了问题,但是呢,随着经营,我们需要假如更多类型的饼干,而且呢,有些饼干销售并不是很好,为了能够跟好的抢占市场,我们必须得做出改变,增加或者是删除某些饼干类型,所以代码需要不同的在红色部分进行修改,也就是说,需要不停的起改变这个类,但是要比起最初依赖实例化的对象的编程的方式要好了很多。到现在为止,我们判断了那些可以改变(红色部分),哪些不可以改变,所以我们把实例化对象创建的改变的部分抽离这个方法,进行封装。

这样的化,orderCookies()方法就可以只关注怎么实现订单,不在关注创建那种类型的饼干,只关注是否有饼干对象进入方法了,所以相对来说,orderCookies()方法更像是抽离代码部分的客户,所以,我们把抽离的部分封装成一个型的对象,这个新对象成为工厂(CookiesFactory),功能就是产生不同类型的饼干,这样刚好和orderCookies方法相结合起来:

public CookiesFactory{public Cookies createCookies(String type){Cookies cookies = null;if("cheese".equals(type)){Cookies = new CheeseCookies();}if("greek".equals(type)){Cookies = new GreekCookies();}if("pepperoni".equals(type)){Cookies = new PepperoniCookies();}return cookies;}}
到现在为止,已经实现了在客户的代码中删除了具体的实例化对象的过程,而且,CookiesFactory类有很多的客户,不单独仅限于点单客户,还可以有菜单呀,宅急送等等的。当然呢,有的胡说可以将其设置为一个静态的工厂,这个也可以,不过这样的话就不能够通过继承的方式改变创建方法的行为。

所以,当我们抽离代码后,CookiesStore类有了变化:

public CookiesStore{CookiesFactory factory;public CookiesStore(CookiesFactory factory){this.factory=factory;}public Cookies orderCookies(String type){Cookies cookies; cookies = factory.createCookies(type); cookies.prepare();cookies.bake();cookies.box();return cookies;}}
     在这里使用factory的方法来创建Cookies,使用type确定类型,在实例化Cookies抽象类的某个子类的时候,根据type的类型就可以确定创建何种类型的Cookies;当初始化CookiesStore时,需要传入一个CookiesFactory对象,这个对象结合参数用来创建Cookies,从而实现了分离。上述的方法可以称为简单工厂。


然而呢随着生意越做越大,我们需要开设一些加盟的连锁店,所以在各个地区的连锁店大多会照顾自己本地人的生活习惯以及饮食方式偏好等,所以呢,各个店都会创建自己本地的合适的类型,所以当我们按照简单工厂的化也可以做出来,但是呢我们希望多一些的控制,比如,可以把加盟店和饼干的创建方式绑定起来,同时又可以有一定的弹性。

经过分析我们可以发现,创建Cookies的方法被局限到每个工厂类里面了,所以呢,为了能够实现我们的期望我们可以将createCookies()方法放回到原来的CookiesStore类中,不过要把这个方法设置为抽象的方法,把这个类设置为抽象类:

public abstract CookiesStore{abstract Cookies createCookies(String type);public Cookies orderCookies(String type){Cookies cookies = createCookies(type);cookies.prepare();cookies.bake();cookies.box();return cookies;}}
   这样的化可以使用CookiesStore类作为一个超类让每个加盟店(北京店,南京店)来继承,这样的化就实现了每个子类自己决定来制造何种Cookies了。同时不要让子类覆写
超类中的orderCookies()方法,可以把它设置为final类型;以北京店为例:

public BeijingCookiesStore extends CookiesStore{public Cookies createCookies(String type){Cookies cookies = null;if("cheese".equals(type)){Cookies = new CheeseCookies();}if("greek".equals(type)){Cookies = new GreekCookies();}if("pepperoni".equals(type)){Cookies = new PepperoniCookies();}return cookies;}}
对于实现让子类做决定则是通过CookiesStore类的orderCookies()方法来看的,它虽然在超类CookiesStore中进行了定义但是呢,对于Cookies的具体的类型其是到了子类中才知道是实现的那种具体的类型。话句话说,orderCookies()方法并不知道实际上是那个子类创建的Cookies。更进一步的说orderCookeis()方法并不知道有哪些实际的具体的类参与了进来,这相当于是解耦。所以说决定者是客户,客户选择北京店,则饼干由北京店来创建。

相比较上面的简单工厂的方法,原来使用一个对象具体的负责所有类的实例化,而现在字是通过CookiesStore类的子类完成负责实例化的任务。下面我们来订购一个饼干:

首先呢我们选择了北京店,chesse类型的饼干:

CookeisStore beijingCookiesStroe = new BeijingCookiesStore();
得到北京点的对象之后我们开始下单定制饼干:

beijingCookiesStore.orderCookies("cheese");
然而,当调用orderCookies()方法时,里面会创建饼干对象:

Cookies cookies = createCookies("cheese");
然后再执行后面方法:

cookies.prepare();cookies.bake();cookies.box();
这样完成了,以上的过程则是使用的工厂方法来实现的,使用其中的一个方法来作为创建实例化对象的拥有者,不在使用一个单独的对象来进行实例化,而是通过子类实现实例化的过程。以上可以称作为工厂方法。












    


原创粉丝点击