工厂模式

来源:互联网 发布:2016新开淘宝运营教程 编辑:程序博客网 时间:2024/05/22 06:49

工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。

工厂模式定义

我们以类Sample为例, 如果我们要创建Sample的实例对象:
Sample sample=new Sample();
可是,实际情况是,通常我们都要在创建sample实例时做点初始化的工作,比如赋值 查询数据库等。
首先,我们想到的是,可以使用Sample的构造函数,这样生成实例就写成:
Sample sample=new Sample(参数);
但是,如果创建sample实例时所做的初始化工作不是像赋值这样简单的事,可能是很长一段代码,如果也写入构造函数中,那你的代码很难看了(就需要Refactor重构)。
为什么说代码很难看,初学者可能没有这种感觉,我们分析如下,初始化工作如果是很长一段代码,说明要做的工作很多,将很多工作装入一个方法中,相当于将很多鸡蛋放在一个篮子里,是很危险的,这也是有悖于Java面向对象的原则,面向对象的封装(Encapsulation)和分派(Delegation)告诉我们,尽量将长的代码分派“切割”成每段,将每段再“封装”起来(减少段和段之间耦合联系性),这样,就会将风险分散,以后如果需要修改,只要更改每段,不会再发生牵一动百的事情。
在本例中,首先,我们需要将创建实例的工作与使用实例的工作分开, 也就是说,让创建实例所需要的大量初始化工作从Sample的构造函数中分离出去。
这时我们就需要Factory工厂模式来生成对象了,不能再用上面简单new Sample(参数)。还有,如果Sample有个继承如MySample, 按照面向接口编程,我们需要将Sample抽象成一个接口.ISample是接口,有两个子类MySample 和HisSample .我们要实例化他们时,如下:
ISample mysample=new MySample();
ISample hissample=new HisSample();
随着项目的深入,Sample可能还会”生出很多儿子出来”, 那么我们要对这些儿子一个个实例化,更糟糕的是,可能还要对以前的代码进行修改:加入后来生出儿子的实例.这在传统程序中是无法避免的。
但如果你一开始就有意识使用了工厂模式,这些麻烦就没有了。

工厂模式的分类

1 简单工厂模式(静态工厂)2 抽象工厂模式3 工厂方法模式下面我们来带着这样的场景来学习工厂设计模式:有一天,林同学准备去买笔记本,他到商城发现有两款电脑他特别喜欢, 一款是 Macbook Pro, 另一款是 Surface Pro。

简单工厂模式的实现

  专门定义一个类用来创建其它类的实例,被创建的实例通常都具有共同的父类。
interface Computer {    public void printComputer();}class MacbookProComputer implements Computer {    public void printComputer() {        System.out.println("This is a macbook pro");    }}class SurfaceBookComputer implements Computer {    public void printComputer() {        System.out.println("This is a surface book");    }}class ComputerFactory {    public Computer createComputer(String type) {        Computer c = null;        if(type.equals("macbook")) {            c = new MacbookProComputer();        }else if(type.equals("surface")) {            c = new SurfaceBookComputer();        }        return c;    }}public class Client {    public void buy(Computer c){        System.out.println("I buy a computer");        c.printComputer();    }    public static void main(String[] args) {        Client c = new Client();        ComputerFactory cf = new ComputerFactory();        Computer computer = cf.createComputer("macbook");        c.buy(computer);    }}

简单工厂模式就是客户想要什么就创建什么,但是当添加新的子类(比如其它品牌电脑的时候,还需要修改工厂类来满足需求),所以简单工厂方法缺点还输比较突出。优缺点如下:
优点:
工厂角色负责产生具体的实例对象,所以在工厂类中需要有必要的逻辑,通过客户的输入能够得到具体创建的实例;所以客户端就不需要感知具体对象是如何产生的,只需要将必要的信息提供给工厂即可。
缺点:
简单工厂模式是违反“开闭原则”,即对扩展开放,对修改关闭;因为如果要新增具体产品,就需要修改工厂类的代码

工厂方法模式:

定义一个用来创建对象的接口,让子类决定实例化哪一个类,让子类决定实例化延迟到子类

interface Computer {    public void printComputer();}class MacbookProComputer implements Computer {    public void printComputer() {        System.out.println("This is a macbook pro");    }}class SurfaceBookComputer implements Computer {    public void printComputer() {        System.out.println("This is a surface book");    }    }interface ComputerFactory {    public Computer createComputer();}class MsFactory implements ComputerFactory {    public Computer createComputer(){        return new SurfaceBookComputer();    }}class AppleFactory implements ComputerFactory {    public Computer createComputer() {        return new MacbookProComputer();    }}public class Client {    public void buy(Computer c){        System.out.println("I buy a computer");        c.printComputer();    }    public static void main(String[] args) {        Client c = new Client();        ComputerFactory cf = new AppleFactory();        Computer computer = cf.createComputer();        c.buy(computer);    }}

工厂方法模式是针对每个产品提供一个工厂类,在客户端中判断使用哪个工厂类去创建对象。
对比简单工厂模式和工厂方法模式:

对于简单工厂模式而言,创建对象的逻辑判断放在了工厂类中,客户不感知具体的类,但是其违背了开闭原则,如果要增加新的具体类,就必须修改工厂类。

对于工厂方法模式而言,是通过扩展来新增具体类的,符合开闭原则,但是在客户端就必须要感知到具体的工厂类,也就是将判断逻辑由简单工厂的工厂类挪到客户端。

工厂模式横向扩展很方便,假如该工厂又有新的产品 Macbook Air 要生产,那么只需要创建相应的工厂类和产品类去实现抽象工厂接口和抽象产品接口即可,而不用去修改原有已经存在的代码。

抽象工厂模式

                提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

工厂方法模式和抽象工厂模式基本类似,可以这么理解:当工厂只生产一个产品的时候,即为工厂方法模式,而工厂如果生产两个或以上的商品即变为抽象工厂模式。

我们在抽象工厂接口中新增创建系统的方法,并由实例工厂类去实现。

interface Computer {    public void printComputer();}class MacbookProComputer implements Computer {    public void printComputer() {        System.out.println("This is a macbook pro");    }}class SurfaceBookComputer implements Computer {    public void printComputer() {        System.out.println("This is a surface book");    }}interface OperatingSystem {    public void printSystem();}class MacOsSystem implements OperatingSystem {    public void printSystem() {        System.out.println("This is a mac os");    }}class Windows8System implements OperatingSystem {    public void printSystem() {        System.out.println("This is a window 8");    }}interface ProductionFactory {    public Computer createComputer();    public OperatingSystem createSystem();}class AppleFactory implements ProductionFactory {    public Computer createComputer() {        return new MacbookProComputer();    }    public OperatingSystem createSystem() {        return new MacOsSystem();    }}class MsFactory implements ProductionFactory {    public Computer createComputer() {        return new SurfaceBookComputer();    }    public OperatingSystem createSystem() {        return new Windows8System();    }}public class Client {    public void buy(Computer c){        System.out.println("I buy a computer");        c.printComputer();    }    public void use(OperatingSystem s) {        System.out.println("Operating System");        s.printSystem();    }    public static void main(String[] args) {        ProductionFactory pf = new AppleFactory();        Computer c = pf.createComputer();        OperatingSystem s = pf.createSystem();        Client client = new Client();        client.buy(c);        client.use(s);    }}

抽象工厂模式的缺点在于产品类的扩展,将会是十分费力的,假如在需要加入新的产品,那么几乎所有的工厂类都需要进行修改,所以在使用抽象工厂模式时,对产品等级结构的划分是十分重要的。

参考资料
http://baike.baidu.com/link?url=I2er-iZPA09iZfjaxLxHyXCmXu0lgpT-20HtZcI1ns5v4I2dM3O3bnRyLa-GhduDx2NJZitREKbSoLkg0IIdOgtXPOl0oayU48ztHKqhJKWseXVu0VSMt90pGK6fdJcr
https://zhuanlan.zhihu.com/p/24650116
https://juejin.im/entry/586f00438d6d81005879553f

0 0