设计模式初探(二)之工厂模式
其实对于工厂模式早在我没有系统的学习设计模式的时候就开始好奇了,觉得spring中好多XXXfactory之类的,创建bean的beanfactory,创建代理proxyfactory,处理事务的transactionfactory,其实不还有简单的工厂方法模式,用于在于hibermate中创建session的sessionfactory,很多地方都用到工厂模式,下面开始讲讲我的理解。
?
工厂模式用于创建规则化对象的创建工作,或者说将代码中用于创建对象的重复出现的new关键字替换成更能体现业务逻辑的类似于createxxx,getxxx方法,再或者说是向用户隐藏对象的构造方法。下面用具体的例子来说明一下:在建立一套公共的企业管理软件中,只要是注册并且提供信息的用户公司都能创建一套自己的办公管理软件,提供服务商只需根据公司的规模,企业方向,运营模式,等等来创建出适合企业的系统,在这其中,服务商提供3个层次大小的系统,公司规模大于1000属S1,间于300到1000的属于S2,300以下的公司属于S3,我在这里用一个叫SystemBuilder的对象去构建系统各个模块。这个对象根据公司规模创建不同的类别的系统:
?
public interface S{public char getId();//这里是系统的其它行为,以供其它的模块实现}public class S1{private char id = 'big';public char getId(){return id;}}public class S2{private char id = 'middle';public char getId(){return id;}}public class S3{private char id = 'small';public char getId(){return id;}}?下面是一个工厂类,SystemBuilder:
?
public class SystemBuilder{public static S getSystem(int nums){private S sysm;if(nums>1000){sysm = new S1();//这里不写return new S1(),是因为在返回实例的过程中可以对system进行初始化工作return sysm;}else if(nums<=1000&&nums>300){sysm = new S2();return sysm;}else if(nums<=300){sysm = new S3();return sysm;}} }?在创建S实例的时候只需要得到一个SystemBuilder的引用,然后根据公司规模创建不同类型的系统:
?
S s = SystemBuilder.getSystem(XXX);s.getId();
上面的示例中的SystemBuilder其实就是一个简单工厂,说它简单,是因为在其中只能创建3种类型的系统,如果在以后功能扩展中需要对系统规模进行细分的时候就需要更改创建方法,这样势必造成难以扩展,不过我觉得如果在规模上进行细分不会扩展成很多类型,简单工厂模式还是很适合的,所以,对于在所需对象类型上不是需求变化或者说变化不多,这就是simplefactory的运用动机。
那好,现在已经创建好了系统的基本框架,现在需要为不同的需求订制不同的系统权限管理模块,每一个公司都有不同的权限管理的方案,每一个公司都可以根据自身的方案订制不同的系统自模块,P1,P2,P3。。。。这些不同方案的权限管理模块的创建自然是不适用于简单工厂模式,因为如果注册公司在以知的方案中未找到符合的,那服务商就必须创建新的方案,这样的要求我想在现实中是经常碰到的,所以这里就用到了factorymethod模式,将权限管理的模块生成延迟到每一个对应的子类中:
?
public interface S{public char getId();//这里是系统的其它行为,以供其它的模块实现public PermissionManager createPermissionManager(); }public class S1{private char id = 'big';public char getId(){return id;}public PermissionManager createPermissionManager(){return new PermissionManagerS1();}}public class S2{private char id = 'middle';public char getId(){return id;}public PermissionManager createPermissionManager(){return new PermissionManagerS2();}}public class S3{private char id = 'small';public char getId(){return id;}public PermissionManager createPermissionManager(){return new PermissionManagerS3();}}?仅仅是改了一下S类的代码,将用简单工厂创建出来的的S对象,创建对应的系统权限管理模块,这里createPermissionManager就是一个工厂方法,将创建对象的时机延迟到子类,也就是SXXX中,当然我在这里只是为了说明工厂方法的声明,这里在每一个子类中的方法的实现对具体的方案产生了耦合,只需声明一个公共的permissionmanager接口,在分别创建不同方案的不同类,在返回具体模块的时候利用参数,创建对象即可,这里就不写了。。
在第二个例子中,权限管理模块是在系统模块中创建的,是低于系统类这个层次的,即先创建系统对象,再创建子模块, 如果在创建某些平行层次对象的时候,并且这些相同层次的对象依赖于同一平台,下面就用到抽象工厂模式:
?
抽象工厂的涵义是提供一个创建一系列相互依赖对象的接口或者抽象类,而实际的创建是在子类中实现的。
下面就用java实现Gof中关于抽象工厂的例子(我觉得这个例子是最形象具体的了,所以就想不出什么好的例子了),首先声明一个用于创建窗口和滑动条的接口:
?
public interface WidgetFactory{public ScrollBar createScrollBar();public Window createWindow();}?
?对于不同的操作视感(PM和Motif),工厂产生的对象会用具体的子类去产生,也就是PMWidgetFactory和MotifWidgetFactory:
?
public class PMWidgetFactory implements WidgetFactory{public ScrollBar createScrollBar(){return new PMScrollBar();}public Window createWindow(){return new PMWindow();}}public class MotifWidgetFactory implements WidgetFactory{public ScrollBar createScrollBar(){return new MotifScrollBar();}public Window createWindow(){return new MotifWindow();}}?
?下面是Window和ScrollBar的接口及具体不同平台的实现:
?
public interface Window{ public void name();}public interface ScrollBar{public void name();}public class MotifWindow implements Window{public void name(){System.out.println("this is a MotifWindow");}}public class PMWindow implements Window{public void name(){System.out.println("this is PMWindow");}}public class MotifScrollBar implements ScrollBar{public void name(){System.out.println("this is MotifScrollBar");}}public class PMScrollBar implements ScrollBar{public void name(){System.out.println("this is a PMScrollBar");}}?在调用的时候只需创建具体平台的工厂类,然后调用工厂方法:
?
public class Test {public static void main(String arg[]){WidgetFactory pmf = new PMWidgetFactory(); Window pmWin = pmf.createWindow();ScrollBar pmSb = pmf.createScrollBar();pmWin.name();pmSb.name(); }}?这样,就实现了相同平台的构建依赖对象,但是还有人提出;
?
WidgetFactory pmf = new PMWidgetFactory();
?这样不还是还是需要具体创建需求的工厂,然后才能创建组件吗?其实,我觉得这里的抽象工厂模式的目的不是为了隐藏具体的产生对象的工厂,而是为了创建具有一系列对象中的一个的时候,并且可以产生变换的产品,为的是系统的可扩展性和维护,如果非要说想隐藏具体工厂的创建,那么就结合简单工厂或者工厂方法将工厂的创建都封装,通过参数对其实例化请求。。
?
?
?
?