[DesignPattern] 设计之禅读书笔记(二) 工厂模式

  • 工厂模式

    • Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclass. (定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到了子类。)

    • 图例

    • 通用代码

      public abstract class Product {
        //产品类的公共方法  
        public void method1() {
            //business logic 
        }    
      
        //抽象方法
        public abstract void method2();
      }
      
      public class ConcreteProduct1 extends Product {
          public void method2(){
              // business logic
          } 
      } 
      
      public class ConcreteProduct2 extends Product {
          public void method2(){
              // business logic
          }
      }
      
      public abstract class Creator {
          /*
          * 创建一个一个产品对象,其输入参数类型可以自行设置
          * 通常为String Enum Class等, 当然也可以为空
          *
          public abstract <T extends Product> T createProduct(Class<T> c);
      }
      
      public class ConcreteCreator extends Creator {
          public <T extends Product> T createProduct(Class<T> c) {
              Product product = null;
              try {
                  product = (Product)Class.forName(c.getName().newInstance());
              } catch (Exception e){}
              return (T)product;
          }
      }
      
      public class Client {
          public static void main(String[] args) {
              Creator creator = new ConcreteCreator();
              Product product = creator.createProduct(ConcreteProduct1.class);
          }
      }
      
      • 工厂模式的优点

        1. 良好的封装性,代码结构清晰
        2. 工厂方法的扩展性非常优秀
        3. 屏蔽产品类
        4. 工厂方法模式是典型的解耦框架
      • 工厂模式的使用场景

        1. 工厂方法模式是new一个对象的替代品,所以在所有需要的对象的地方都可以使用, 但是需要谨慎考虑是否需要增加一个工厂类进行管理,增加代码的复杂性。
        2. 需要灵活的、可扩展的框架时,可以考虑采用工厂方法模式。
        3. 工厂方法模式可以在异构项目中使用。
        4. 可以在测试驱动开发的框架下使用
      • 例子:女娲造人

      //人的接口
      public interface Human {
        public void getColor();
        public void talk();
      }
      
      //具体的人
      public class WhiteHuman implements Human {
        @Override
        public void getColor() {
          System.out.println("White skin");
        }
      
        @Override
        public void talk() {
          System.out.println("My skin is white");
        }
      }
      public class BlackHuman implements Human {
        @Override
        public void getColor() {
          System.out.println("Black skin");
        }
      
        @Override
        public void talk() {
          System.out.println("My skin is black");
        }
      }
      public class YellowHuman implements Human {
        @Override
        public void getColor() {
          System.out.println("Yellow skin");
        }
      
        @Override
        public void talk() {
            System.out.println("My skin is yellow");
        }
      }
      
      //造人的抽象工厂
      public abstract class AbstractHumanFactory {
        public abstract <T extends Human> T createHuman(Class<T> c);
      }
      
      //具体的造人
      public class HumanFactory extends AbstractHumanFactory {
        @Override
        public <T extends Human> T createHuman(Class<T> c) {
          Human human = null;
          try {
            human = (T) Class.forName(c.getName()).getDeclaredConstructor().newInstance();
          } catch (Exception e) {
            System.out.println("Having problem when create human");
          }
          return (T)human;
        }
      }
      
      //女娲
      public class NvWa {
        public static void main(String[] args) {
          AbstractHumanFactory YinYangLu = new HumanFactory();
          System.out.println("------------------------");
          Human whiteHuman = YinYangLu.createHuman(WhiteHuman.class);
          whiteHuman.getColor();
          whiteHuman.talk();
          System.out.println("------------------------");
          Human yellowHuman = YinYangLu.createHuman(YellowHuman.class);
          yellowHuman.getColor();
          yellowHuman.talk();
          System.out.println("------------------------");
          Human blackHuman = YinYangLu.createHuman(BlackHuman.class);
          blackHuman.getColor();
          blackHuman.talk();
        }
      }
      
    • 扩展

      • 简单工厂
        • 一个模块如果只需要一个工厂类,没有必要把它生产出来, 使用静态的方法就可以了
        • 对于上面的例子来说,去掉abstractHumanFacotry, 同时把createHuman方法设置成静态类。
        • 在实际项目中,采用该方法的案例还是比较多的, 优点是比较简单,缺点是工厂类扩展比较困难, 不符合开闭原则, 但它仍然是一个很实用的设计模式。
        • 例子
        public class HumanFactory {
          public static <T extends Human> T createHuman(Class<T> c) {
            Human human = null;
            try {
              human = (T) Class.forName(c.getName()).getDeclaredConstructor().newInstance();
            } catch (Exception e) {
              System.out.println("Having problem when create human");
            }
            return (T) human;
          }
        }
        
        public class NvWa {
          public static void main(String[] args) {
            System.out.println("------------------------");
            Human whiteHuman = HumanFactory.createHuman(WhiteHuman.class);
            whiteHuman.getColor();
            whiteHuman.talk();
            System.out.println("------------------------");
            Human yellowHuman = HumanFactory.createHuman(YellowHuman.class);
            yellowHuman.getColor();
            yellowHuman.talk();
            System.out.println("------------------------");
            Human blackHuman = HumanFactory.createHuman(BlackHuman.class);
            blackHuman.getColor();
            blackHuman.talk();
          }
        }
        
      • 升级为多个工厂类
        • 具体的产品类都对应了一个创造者, 每个创建者都独立船舰对应的产品对象,非常符合单一职责原则
        • 更改上面的例子,对每个不同肤色的人都有自己的工厂,同时因为每个工厂负责自己创建相关类,所以抽象工厂不再需要传递参数。
        • 例子
        public abstract class AbstractHumanFactory {
          public abstract Human createHuman();
        }
        
        public class BlackHumanFactory extends AbstractHumanFactory {
          @Override
          public Human createHuman() {
            return new BlackHuman();
          }
        }
        
        public class WhiteHumanFactory extends AbstractHumanFactory {
          @Override
          public Human createHuman() {
            return new WhiteHuman();
          }
        }
        
        public class YellowHumanFactory extends AbstractHumanFactory {
          @Override
          public Human createHuman() {
            return new YellowHuman();
          }
        }
        
        public class NvWa {
          public static void main(String[] args) {
            System.out.println("------------------------");
            Human whiteHuman = (new WhiteHumanFactory()).createHuman();
            whiteHuman.getColor();
            whiteHuman.talk();
            System.out.println("------------------------");
            Human yellowHuman = (new YellowHumanFactory()).createHuman();
            yellowHuman.getColor();
            yellowHuman.talk();
            System.out.println("------------------------");
            Human blackHuman = (new BlackHumanFactory()).createHuman();
            blackHuman.getColor();
            blackHuman.talk();
          }
        }
        
      • 替代单例模式
        • 可以代替单例,但是觉得没啥必要
        • 例子
        public class Singleton {
          private Singleton(){}
          public void doSomething(){}
        }
        
        public class SingletonFactory {
          private static Singleton singleton;
          static {
            try {
              Class cl = Class.forName(Singleton.class.getName());
              Constructor constructor = cl.getDeclaredConstructor();
              constructor.setAccessible(true);
              singleton = (Singleton)constructor.newInstance();
            } catch (Exception e) {
        
            }
          }
          public static Singleton getSingleton() {
            return singleton;
          }
        }
        
        • 延迟初始化(Lazy initialization)
          • 一个对象被消费完毕后,并不立刻释放,工厂类保持其初始状态,等待再次被使用。
          • 延迟加载框架是可以扩展的,例如限制某一个产品的最大实例化数量。
          • 图示
          • 例子
          public class ProductFactory {
            private static final Map<String, Product> prMap = new HashMap();
            public static synchronized Product createProduct(String Type) throws Exception {
              Product product = null;
              if (prMap.containsKey(type)) {
                product = preMap.get(type);
              } else {
                if (type.equals("Product1")) {
                  product = new ConcreteProduct1();
                } else {
                  product = new ConcreteProduct2();
                }
                prMap.put(type.product);
              }
            }
            return product;
          }
          
          

posted on 2020-10-14 11:53  codingEskimo  阅读(56)  评论(0编辑  收藏  举报

导航