Spring之工厂模式

来源:互联网 发布:三盛网络机柜 编辑:程序博客网 时间:2024/05/07 08:01


简单工厂模式(Simple Factory)和工厂方法模式(Factory Method)

在OO设计领域涉及到的几个原则:

OCP(开闭原则,Open-Closed Principle):一个软件的实体应当对扩展开放,对修改关闭。我的理解是,对于一个已有的软件,如果需要扩展,应当在不需修改已有代码的基础上进行。
DIP(依赖倒转原则,Dependence Inversion Principle):要针对接口编程,不要针对实现编程。我的理解是,对于不同层次的编程,高层次暴露给低层次的应当只是接口,而不是它的具体类。
LoD(迪米特法则,Law of Demeter):只与你直接的朋友通信,而避免和陌生人通信。众所周知类(或模块)之间的通信越少,耦合度就越低,从而更有利于我们对软件的宏观管理。

简单工厂模式及实例
简单工厂模式又叫静态工厂模式,顾名思义,它是用来实例化目标类的静态类。下面我主要通过一个简单的实例说明简单工厂及其优点。
比如有个国家的运动员协会,他们是负责登记与注册职业运动员的(就好像我们国家的体育总局,呵呵,无论足球篮球还是乒乓球的运动员都必须在这里注册才能拿到我们国家职业运动员牌照)。一家体育俱乐部(比如篮球的广东宏远,足球的深圳健力宝)想获得球员为自己俱乐部效力,就必须通过这个运动员协会。
根据DIP我们可以设计一个“运动员”接口,“足球运动员”和“篮球运动员”(还有其他运动员)都实现“运动员”这个接口。而“运动员协会”就是一个简单工厂类,它负责实例化“运动员”。我们这里的“俱乐部”就是一个客户端(Client),不同的“俱乐部”就是不同的客户端。具体如下图表示:

对于不同的俱乐部对象(无论是八一还是深圳健力宝),他们都是面向“运动员”接口编程,而不用管是“足球运动员”还是“篮球运动员”,也就是说实现了“运动员”接口的具体类“足球运动员”无需暴露给客户端。这也满足了DIP。但具体的俱乐部(比如足球的深圳健力宝)如何确保自己获取的是自己想要的运
动员(健力宝俱乐部需要的当然是足球运动员)呢?这就需要“运动员协会”这一工厂类了。俱乐部通过调用“运动员协会”的具体方法,返回不同的实例。这同时也满足了LoD,也就是“深圳健力宝足球俱乐部”对象不直接与“足球运动员:李毅”对象通信,而是通过他们共同的“朋友”——“国家体育总局”通信。

下面给出各个类的程序,会有助于读者更好的了解笔者之前的介绍。
运动员.java
public interface 运动员 {       
        public void 跑();
        public void 跳();
}
足球运动员.java
public class 足球运动员 implements 运动员 {
        public void 跑(){
                //跑啊跑
        }
        public void 跳(){
                //跳啊跳
        }
}
篮球运动员.java
public class 篮球运动员 implements 运动员 {
        public void 跑(){
                //do nothing
        }
        public void 跳(){
                //do nothing
        }
}
体育协会.java
public class 体育协会 {      
        public static 运动员 注册足球运动员(){
                return new 足球运动员();
        }
        public static 运动员 注册篮球运动员(){
                return new 篮球运动员();
        }
}
俱乐部.java
public class 俱乐部 {
        private 运动员 守门员;
        private 运动员 后卫;
        private 运动员 前锋;

        public void test() {
                this.前锋 = 体育协会.注册足球运动员();
                this.后卫 = 体育协会.注册足球运动员();
                this.守门员 = 体育协会.注册足球运动员();
                守门员.跑();
                后卫.跳();
        }
}
以上就是简单工厂模式的一个简单实例,读者应该想象不用接口不用工厂而把具体类暴露给客户端的那种混乱情形吧(就好像没了体育总局,各个俱乐部在市场上自己胡乱的寻找仔细需要的运动员),简单工厂就解决了这种混乱。

我们用OCP看看简单工厂,会发现如果要对系统进行扩展的话治需要增加实现产品接口的产品类(上例表现为“足球运动员”,“篮球运动员”类,比如要增加个“乒乓球运动员”类),而无需对原有的产品类进行修改。这咋一看好像满足OCP,但是实际上还是需要修改代码的——对,就是修改工厂类。上例中如果增加“乒乓球运动员”产品类,就必须相应的修改“体育协会”工厂类,增加个“注册乒乓球运动员”方法。所以可以看出,简单工厂模式是不满足OCP的。

工厂方法模式及其实例
前一节的最末点明了简单工厂模式最大的缺点——不完全满足OCP。为了解决这一缺点,设计师们提出了工厂方法模式。工厂方法模式和简单工厂模式最大的不同在于,简单工厂模式只有一个(对于一个项目或者一个独立模块而言)工厂类,而工厂方法模式有一组实现了相同接口的工厂类。下面我们通过修改上一节的实例来介绍工厂方法模式。
我们在不改变产品类(“足球运动员”类和“篮球运动员”类)的情况下,修改下工厂类的结构,如下图所示:
运动员.java
public interface 运动员 {       
        public void 跑();
        public void 跳();
}
足球运动员.java
public class 足球运动员 implements 运动员 {

        public void 跑(){
                //跑啊跑
        }
       
        public void 跳(){
                //跳啊跳
        }
}
篮球运动员.java
public class 篮球运动员 implements 运动员 {

        public void 跑(){
                //do nothing
        }
       
        public void 跳(){
                //do nothing
        }
}
体育协会.java
public interface 体育协会 {
        public 运动员 注册();
}
足球协会.java
public class 足球协会 implements 体育协会 {
        public 运动员 注册(){
                return new 足球运动员();
        }
}
篮球协会.java
public class 篮球协会 implements 体育协会 {
        public 运动员 注册(){
                return new 篮球运动员();
        }
}
俱乐部.java
public class 俱乐部 {
        private 运动员 守门员;
        private 运动员 后卫;
        private 运动员 前锋;

        public void test() {
                体育协会 中国足协 = new 足球协会();
                this.前锋 = 中国足协.注册();
                this.后卫 = 中国足协.注册();
                守门员.跑();
                后卫.跳();
        }
}
很明显可以看到,“体育协会”工厂类变成了“体育协会”接口,而实现此接口的分别是“足球协会”“篮球协会”等等具体的工厂类。
这样做有什么好处呢?很明显,这样做就完全OCP了。如果需要再加入(或扩展)产品类(比如加多个“乒乓球运动员”)的话就不再需要修改工厂类了,而只需相应的再添加一个实现了工厂接口(“体育协会”接口)的具体工厂类。

工大后院版权所有

0 0