1. 工厂方法设计模式类图
2. 手机工厂举例
package 工厂方法设计模式_手机工厂举例;
interface Mobile
{
void Call();
}
interface MobileFactory
{
Mobile ProduceMobile();
}
class Motorola implements Mobile
{
public void Call()
{
System.out.println("摩托罗拉手机");
}
}
class Nokia implements Mobile
{
public void Call()
{
System.out.println("诺基亚手机");
}
}
class MotorolaFactory implements MobileFactory
{
public Mobile ProduceMobile()
{
System.out.println("摩托罗拉工厂制造了");
return new Motorola();
}
}
class NokiaFactory implements MobileFactory
{
public Mobile ProduceMobile()
{
System.out.println("诺基亚工厂制造了");
return new Nokia();
}
}
public class Client {
public static void main(String[] args) {
MobileFactory factory;
Mobile mobile;
factory = new MotorolaFactory();
mobile = factory.ProduceMobile();
mobile.Call();
factory = new NokiaFactory();
mobile = factory.ProduceMobile();
mobile.Call();
}
}
3. 简单工厂与工厂方法的对比:
简单工厂的优点:
简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相应的类。
对于客户端来说,去除了与具体产品的依赖。
简单工厂的问题:
如果要加功能,是一定需要给工厂类的方法里加如'case'的分支条件的,修改原有的类?
意思是我们不但对扩展开放了,对修改也开放了,违背了开放-封闭原则
工厂方法对整个工厂和产品体系都没有修改的变化,而只是扩展的变化,符合开放-封闭原则。工厂方法实现时,客户端需要决定实例化哪一个工厂来生成产品,选择的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑移到了客户端代码来进行。你想要加功能,本来是改工厂类的,现在是修改客户端。
4. 《Java编程思想》中关于工厂方法模式的举例:
接口是实现多重继承的途径,而生成遵循某个接口的对象的典型方式就是工厂方法设计模式。这与直接调用构造器不同,我们在工厂对象上调用的是创建方法,而该工厂对象将生成接口的某个实现的对象。理论上,通过这种方式,我们的代码将完全与接口的实现分离,这就使得我们可以透明地将某个实现替换为另一个实现。
package 工厂方法设计模式_接口;
//: interfaces/Factories.java
import static net.mindview.util.Print.*;
interface Service {
void method1();
void method2();
}
interface ServiceFactory {
Service getService();
}
class Implementation1 implements Service {
Implementation1() {
} // Package access
public void method1() {
print("Implementation1 method1");
}
public void method2() {
print("Implementation1 method2");
}
}
class Implementation1Factory implements ServiceFactory {
public Service getService() {
return new Implementation1();
}
}
class Implementation2 implements Service {
Implementation2() {
} // Package access
public void method1() {
print("Implementation2 method1");
}
public void method2() {
print("Implementation2 method2");
}
}
class Implementation2Factory implements ServiceFactory {
public Service getService() {
return new Implementation2();
}
}
public class Client {
public static void serviceConsumer(ServiceFactory fact) {
Service s = fact.getService();
s.method1();
s.method2();
}
public static void main(String[] args) {
serviceConsumer(new Implementation1Factory());
// Implementations are completely interchangeable:
serviceConsumer(new Implementation2Factory());
}
} /*
* Output: Implementation1 method1 Implementation1 method2 Implementation2
* method1 Implementation2 method2
*/// :~
5. 使用匿名内部类实现工厂方法设计模式
为什么需要内部类?
1)如果一个类想继承两个父类,只能使用内部类来实现这种多重继承
2)如果一个类想实现两个接口,那么可以有两个选择
使用单一类实现这两个接口
使用内部类来实现其中的一个或两个接口。使用内部类带来更大的灵活性。
比如说你可以让多个内部类以不同的方式实现同一个接口,或继承同一个类
工厂方法模式中就是这种用法的体现
两个匿名内部工厂类都实现工厂类,但getService方法返回不同的服务
package 工厂方法设计模式_匿名内部类;
//: innerclasses/Factories.java
import static net.mindview.util.Print.*;
interface Service {
void method1();
void method2();
}
interface ServiceFactory {
Service getService();
}
class Implementation1 implements Service {
private Implementation1() {
}
public void method1() {
print("Implementation1 method1");
}
public void method2() {
print("Implementation1 method2");
}
public static ServiceFactory factory = new ServiceFactory() {
public Service getService() {
return new Implementation1();
}
};
}
class Implementation2 implements Service {
private Implementation2() {
}
public void method1() {
print("Implementation2 method1");
}
public void method2() {
print("Implementation2 method2");
}
public static ServiceFactory factory = new ServiceFactory() {
public Service getService() {
return new Implementation2();
}
};
}
public class Client {
public static void serviceConsumer(ServiceFactory fact) {
Service s = fact.getService();
s.method1();
s.method2();
}
public static void main(String[] args) {
serviceConsumer(Implementation1.factory);
// Implementations are completely interchangeable:
serviceConsumer(Implementation2.factory);
}
} /*
* Output: Implementation1 method1 Implementation1 method2 Implementation2
* method1 Implementation2 method2
*/// :~