zoukankan      html  css  js  c++  java
  • 工厂方法

    1、接口与工厂

    接口是实现多重继承的途径,而生成遵循某个接口的对象的典型方式就是 工厂方法 设计模式。这与直接调用构造器不同,我们在工厂对象上调用的是创建方法(类似于Factory.build()),而该工厂对象将生成接口的某个实现的对象。理论上,通过这种方式,我们的代码将完全与接口的实现分离,这就使得我们可以透明地将某个实现替换为另一个实现。下面的实例展示了工厂方法的结构

    //: interfaces/Factories.java
    
    interface Service {
      void method1();
      void method2();
    }
    
    interface ServiceFactory {
      Service getService();
    }
    
    // 实现服务接口
    class Implementation1 implements Service {
      Implementation1() {} // Package access
      public void method1() {System.out.println("Implementation1 method1");}
      public void method2() {System.out.println("Implementation1 method2");}
    }	
    
    // 实现服务工厂接口
    class Implementation1Factory implements ServiceFactory {
      public Service getService() {
        return new Implementation1(); // 返回一个Service的实现类对象
      }
    }
    
    class Implementation2 implements Service {
      Implementation2() {} // Package access
      public void method1() {System.out.println("Implementation2 method1");}
      public void method2() {System.out.println("Implementation2 method2");}
    }
    
    class Implementation2Factory implements ServiceFactory {
      public Service getService() {
        return new Implementation2();
      }
    }	
    
    public class Factories {
      // 这里在实际调用的时候,就会出现差别了,也就是可以传入不同的实现类,从而生产不同的产品对象
      public static void serviceConsumer(ServiceFactory fact) {
        Service s = fact.getService();
        s.method1();
        s.method2();
      }
      public static void main(String[] args) {
        serviceConsumer(new Implementation1Factory()); // 生产一个实现类1
        // Implementations are completely interchangeable:
        serviceConsumer(new Implementation2Factory()); // 生产一个实现类2
      }
    } /* Output:
    Implementation1 method1
    Implementation1 method2
    Implementation2 method1
    Implementation2 method2
    *///:~
    

    如果不是用工厂方法,你的代码就必须在某处指定将要创建的Service的确切类型,以便调用合适的构造器。即,使用工厂方法的话,你可以把接口作为 serviceConsumer 的参数,然后调用的时候可以传入这个接口的不同的实现类,以达到生产不同的对象的目的。

    具体的小示例——在相同的棋盘上下国际象棋和西洋跳棋:

    //: interfaces/Games.java
    // A Game framework using Factory Methods.
    
    // 相当于Service
    interface Game {
        boolean move();
    }
    
    // 相当于ServiceFactory
    interface GameFactory {
        Game getGame();
    }
    
    // 实现类Checkers
    class Checkers implements Game {
        private int moves = 0;
        private static final int MOVES = 3;
    
        public boolean move() {
            System.out.println("Checkers move " + moves);
            return ++moves != MOVES;
        }
    }
    
    class CheckersFactory implements GameFactory {
        public Game getGame() {
            return new Checkers();
        }
    }
    
    // 实现类Chess
    class Chess implements Game {
        private int moves = 0;
        private static final int MOVES = 4;
    
        public boolean move() {
            System.out.println("Chess move " + moves);
            return ++moves != MOVES;
        }
    }
    
    class ChessFactory implements GameFactory {
        public Game getGame() {
            return new Chess();
        }
    }
    
    public class Games {
        // 根据传入对象的不同,来生产不同的对象
        public static void playGame(GameFactory factory) {
            Game s = factory.getGame();
            while (s.move()) ;
        }
    
        public static void main(String[] args) {
            playGame(new CheckersFactory());
            playGame(new ChessFactory());
        }
    } /* Output:
    Checkers move 0
    Checkers move 1
    Checkers move 2
    Chess move 0
    Chess move 1
    Chess move 2
    Chess move 3
    *///:~
    

    2、更优雅的工厂实现方式——匿名内部类

    结构的改造

    //: innerclasses/Factories.java
    
    
    interface Service {
      void method1();
      void method2();
    }
    
    interface ServiceFactory {
      Service getService();
    }	
    
    class Implementation1 implements Service {
      private Implementation1() {}
      public void method1() {System.out.println("Implementation1 method1");}
      public void method2() {System.out.println("Implementation1 method2");}
      public static ServiceFactory factory =
        new ServiceFactory() {
          public Service getService() {
            return new Implementation1();
          }
        };
    }	
    
    class Implementation2 implements Service {
      private Implementation2() {}
      public void method1() {System.out.println("Implementation2 method1");}
      public void method2() {System.out.println("Implementation2 method2");}
      public static ServiceFactory factory =
        new ServiceFactory() {
          public Service getService() {
            return new Implementation2();
          }
        };
    }	
    
    public class Factories {
      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
    *///:~
    

    现在用于Implementation1和Implementation2的构造器都可以是private的(第一种没有用匿名内部类的工厂方法其构造器则是包权限的),并且没有任何必要去创建作为工厂的具名类。另外,你经常只需要单一的工厂对象,因此在本例中它被创建为Service实现中的一个static域。

    Games示例的改造

    //: innerclasses/Games.java
    // Using anonymous inner classes with the Game framework.
    
    interface Game { boolean move(); }
    interface GameFactory { Game getGame(); }
    
    class Checkers implements Game {
      private Checkers() {}
      private int moves = 0;
      private static final int MOVES = 3;
      public boolean move() {
        System.out.println("Checkers move " + moves);
        return ++moves != MOVES;
      }
      public static GameFactory factory = new GameFactory() {
        public Game getGame() { return new Checkers(); }
      };
    }	
    
    class Chess implements Game {
      private Chess() {}
      private int moves = 0;
      private static final int MOVES = 4;
      public boolean move() {
        System.out.println("Chess move " + moves);
        return ++moves != MOVES;
      }
      public static GameFactory factory = new GameFactory() {
        public Game getGame() { return new Chess(); }
      };
    }	
    
    public class Games {
      public static void playGame(GameFactory factory) {
        Game s = factory.getGame();
        while(s.move())
          ;
      }
      public static void main(String[] args) {
        playGame(Checkers.factory);
        playGame(Chess.factory);
      }
    } /* Output:
    Checkers move 0
    Checkers move 1
    Checkers move 2
    Chess move 0
    Chess move 1
    Chess move 2
    Chess move 3
    *///:~
    

    3、使用工厂方法的其他示例

    注册工厂

    //: typeinfo/factory/Factory.java
    package typeinfo.factory;
    public interface Factory<T> { T create(); } ///:~
    
    //: typeinfo/RegisteredFactories.java
    // Registering Class Factories in the base class.
    import typeinfo.factory.*;
    import java.util.*;
    
    class Part {
      public String toString() {
        return getClass().getSimpleName();
      }
      static List<Factory<? extends Part>> partFactories =
        new ArrayList<Factory<? extends Part>>();	
      static {
        // Collections.addAll() gives an "unchecked generic
        // array creation ... for varargs parameter" warning. 所以这里只能用add()方法
        partFactories.add(new FuelFilter.Factory());
        partFactories.add(new AirFilter.Factory());
        partFactories.add(new CabinAirFilter.Factory());
        partFactories.add(new OilFilter.Factory());
        partFactories.add(new FanBelt.Factory());
        partFactories.add(new PowerSteeringBelt.Factory());
        partFactories.add(new GeneratorBelt.Factory());
      }
      private static Random rand = new Random(47);
      public static Part createRandom() {
        int n = rand.nextInt(partFactories.size());
        return partFactories.get(n).create();
      }
    }	
    
    class Filter extends Part {}
    
    class FuelFilter extends Filter {
      // Create a Class Factory for each specific type:
      public static class Factory
      implements typeinfo.factory.Factory<FuelFilter> {
        public FuelFilter create() { return new FuelFilter(); }
      }
    }
    
    class AirFilter extends Filter {
      // 重用Factory这个名字的唯一方式就是限定typeinfo.factory.Factory
      public static class Factory
      implements typeinfo.factory.Factory<AirFilter> {
        public AirFilter create() { return new AirFilter(); }
      }
    }	
    
    class CabinAirFilter extends Filter {
      public static class Factory
      implements typeinfo.factory.Factory<CabinAirFilter> {
        public CabinAirFilter create() {
          return new CabinAirFilter();
        }
      }
    }
    
    class OilFilter extends Filter {
      public static class Factory
      implements typeinfo.factory.Factory<OilFilter> {
        public OilFilter create() { return new OilFilter(); }
      }
    }	
    
    class Belt extends Part {}
    
    class FanBelt extends Belt {
      public static class Factory
      implements typeinfo.factory.Factory<FanBelt> {
        public FanBelt create() { return new FanBelt(); }
      }
    }
    
    class GeneratorBelt extends Belt {
      public static class Factory
      implements typeinfo.factory.Factory<GeneratorBelt> {
        public GeneratorBelt create() {
          return new GeneratorBelt();
        }
      }
    }	
    
    class PowerSteeringBelt extends Belt {
      public static class Factory
      implements typeinfo.factory.Factory<PowerSteeringBelt> {
        public PowerSteeringBelt create() {
          return new PowerSteeringBelt();
        }
      }
    }	
    
    public class RegisteredFactories {
      public static void main(String[] args) {
        for(int i = 0; i < 10; i++)
          System.out.println(Part.createRandom());
      }
    } /* Output:
    GeneratorBelt
    CabinAirFilter
    GeneratorBelt
    AirFilter
    PowerSteeringBelt
    CabinAirFilter
    FuelFilter
    PowerSteeringBelt
    PowerSteeringBelt
    FuelFilter
    *///:~
    
  • 相关阅读:
    show proceslist时发现大量的sleep,有什么风险吗,该如何处理?
    监控MySQL的性能,应该主要观察那几个监控项?
    MySQL所有的压力都在一个CPU核心上,为什么会产生这种现象,改如何解决?
    大表,某列无索引,先需要查询该列,删除符合条件的记录,大约占40%数据量,请问有何更好的方案吗?
    MySQL DBA运维中那些动作属于危险性操作?
    云环境上自建MySQL,有哪些高可用实现方案?
    RDS上,MySQL实例中某张表数据小于tmp_table_size,但有查询时会报错临时空间满 The table '/data/mysql/zst/tmp/#sql_13975_23' is full. 原因可能是什么?
    MySQL误删除frm文件该怎么办?
    生产环境MySQL死锁如何监控及如何减少死锁发生的概率。
    MongoDB有哪些优秀特性及适合的场景是什么?
  • 原文地址:https://www.cnblogs.com/fanlumaster/p/13700401.html
Copyright © 2011-2022 走看看