设计模式1 - 工厂方法模式Factory Method

来源:互联网 发布:苹果电脑的解压缩软件 编辑:程序博客网 时间:2024/05/29 17:32


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

适用性
1.当一个类不知道它所必须创建的对象的类的时候。
2.当一个类希望由它的子类来指定它所创建的对象的时候。
3.当类将创建对象的职责委托给多个帮助子类中的某一个,并且希望将哪一个帮助子类是代理者这一信息局部化的时候。

1 简单工厂模式

Let's consider a simple case in which we could use a Factory class. Suppose we have an entry form and we want to allow the user to enter his name either as "firstname lastname" or as "lastname, firstname." We'll make the further simplifying assumption that we will always be able to decide the name order by whether there is a comma between the last and first name.

public class Namer {    protected String last;    protected String first;    public String getFirst() {        return first;    }    public String getLast() {        return last;                                                                                              }}
public class FirstFirst extends Namer{    public FirstFirst(String s) {        int i = s.lastIndexOf(" ");        if (i > 0) {            first = s.substring(0, i).trim();            last = s.substring(i + 1).trim();        } else {            first = null;            last = s;                                                                                                 }    }}

public class LastFirst extends Namer{    public LastFirst(String s) {        int i = s.indexOf(",");        if (i > 0) {            last = s.substring(0, i).trim();            first = s.substring(i + 1).trim();                                                                        } else {            last = s;            first = "";        }    }}

public class NamerFactory {    public Namer getNamer(String entry) {        int i = entry.indexOf(",");        if (i > 0) {            return new LastFirst(entry);        } else {            return new FirstFirst(entry);                                                                             }    }}

Let's see how we put this together. The complete class diagram is shown:



测试如下:

public class NamerFactoryTest {    public static void main(String[] args) {        String[] names = new String[] {"Song, Guo", "Guo Song"};        NamerFactory factory = new NamerFactory();        for (int i = names.length - 1; i >=0; i-- ) {            System.out.println("----------------");            System.out.println("First:" + factory.getNamer(names[i]).getFirst());            System.out.println("Last:" + factory.getNamer(names[i]).getLast());                                           System.out.println("----------------");        }    }}

输出:



2 工厂方法模式

工厂方法模式角色与结构:

抽象工厂(Creator)角色:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。 

具体工厂(Concrete Creator)角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。在下图中有两个这样的角色:BulbCreator与TubeCreator。

抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。在下图中,这个角色是Light。

具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。


Let's consider an example.

Every program needs a way to report errors. Consider the following interface:

public interface Trace {    // turn on and off debugging    public void setDebug(boolean debug);    //write out a debug message    public void debug(String message);    // write out an error message                                                                                 public void error(String message);}

Suppose that you've written two implementations. One implementation (SystemTrace) writes the messages out to the command line, while another (FileTrace) writes them to a file.

import java.io.PrintWriter;import java.io.FileWriter;import java.io.IOException;public class FileTrace implements Trace{    private PrintWriter pw;    private boolean debug;                                                                                                                  public FileTrace() throws IOException {        // a real FileTrace would need to obtain the filename somewhere        // for the example I'll hardcode it        pw = new PrintWriter(new FileWriter("trace.log"));    }    public void setDebug(boolean debug) {        this.debug = debug;    }    public void debug(String message) {        if (debug) {    // only print if debug is true            pw.println("DEBUG:" + message);            pw.flush();        }    }     public void error( String message ) {        // always print out errors        pw.println( "ERROR: " + message );        pw.flush();    }}

public class SystemTrace implements Trace {      private boolean debug;      public void setDebug( boolean debug ) {            this.debug = debug;      }      public void debug( String message ) {            if( debug ) {  // only print if debug is true                  System.out.println( "DEBUG: " + message );            }      }      public void error( String message ) {            // always print out errors            System.out.println( "ERROR: " + message );      }}

public class TraceFactory {      public static Trace getTrace() {            try {                  return new FileTrace();            } catch ( java.io.IOException ex ) {                  Trace t = new SystemTrace();                  t.error( "could not instantiate FileTrace: " + ex.getMessage() );                  return t;            }      }}

Further, factory methods prove useful when you're not sure what concrete implementation of a class to instantiate. Instead, you can leave those details to the factory method.

In the above examples your program didn't know whether to create FileTrace or SystemTrace instances. Instead, you can program your objects to simply use Trace and leave the instantiation of the concrete implementation to a factory method.



原创粉丝点击