Java-第十八部分-设计模式-工厂模式

155 阅读3分钟

设计模式全文

工厂模式

简单工厂模式

  • 静态工厂模式,属于创建型模式,由一个工厂对象决定创建出哪一种产品类的实例
  • 定义了一个创建对象的类,有这个类来封装实例化对象的行为
  • 案例,实现一个pizza订购功能 demo.png
  • 但是违反了开闭原则,当新增一种pizza时,需要修改内部代码,扩展性不好
  • 改进思路,把创建pizza对象封装到一个类,当有新的pizza时,只需要修改这个类即可

优化

  • 简单工厂优化后,order行为只依赖工厂对象 demo.png
  • 工厂对象
public class SimpleFactory {
    //根据orderType 返回对应的Pizza对象
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if (orderType.equals("greek")) {
            pizza = new GreekPizza();
            pizza.setName("greek");
        } else if (orderType.equals("cheese")) {
            pizza = new CheesePizza();
            pizza.setName("cheese");
        } else if (orderType.equals("pepper")) {
            pizza = new PepperPizza();
            pizza.setName("pepper");
        }
        return pizza;
    }
}
  • order
public OrderPizza(SimpleFactory sf) {
    setSf(sf);
}

public void setSf(SimpleFactory sf) {
    String orderType = "";//用户输入
    this.sf = sf;
    do {
        orderType = getType();
        Pizza pizza = this.sf.createPizza(orderType);
        if (pizza != null) {
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
        } else {
            System.out.println("订购失败");
            break;
        }
    }while (true);
}
  • 将工厂方法写成静态方法的调用
Pizza pizza = null;
String orderType = "";
public OrderPizza() {
    do {
        orderType = getType();
        Pizza pizza = SimpleFactory.createPizza(orderType);
        if (pizza != null) {
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
        } else {
            System.out.println("订购失败");
            break;
        }
    }while (true);
}

工厂方法模式

  • 一个大分类下还有子分类,披萨分北京和伦敦,又分别分奶酪和胡椒
  • 定义一个创建对象的抽象方法,由子类决定要实例化的类,将对象的实例化推迟到子类 demo.png
  • OrderPizza
public abstract class OrderPizza {
    //抽象方法订购pizza
    abstract Pizza createPizza (String orderType);
    public OrderPizza() {构造方法,创建时自动调用}
}
  • BJOrderPizza
public class BJOrderPizza extends OrderPizza{
    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if (orderType.equals("cheese")) {
            pizza = new BJChessPizza();
        } else if (orderType.equals("pepper")) {
            pizza = new BJPepperPizza();
        }
        return pizza;
    }
}
  • LDOrderPizza
public class LDOrderPizza extends OrderPizza{
    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if (orderType.equals("cheese")) {
            pizza = new LDChessPizza();
        } else if (orderType.equals("pepper")) {
            pizza = new LDPepperPizza();
        }
        return pizza;
    }
}

抽象工厂方法

  • 定义了一个interface用于创建相关或有依赖关系的对象簇,无需指明具体的类
  • 将简单工厂模式和工厂方法模式进行整合,对简单工厂模式进一步抽象
  • 将工厂抽象成两层,AbsFactory抽象工厂具体实现的工厂子类,根据创建对象类型使用对应的工厂子类 demo.png
  • AbsFactory
public interface AbsFactory {
    public Pizza createPizza(String orderType);
}
  • BJFactory
public class BJFactory implements AbsFactory{
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if (orderType.equals("cheese")) {
            pizza = new BJChessPizza();
        } else if (orderType.equals("pepper")) {
            pizza = new BJPepperPizza();
        }
        return pizza;
    }
}
  • LDFactory
public class LDFactory implements AbsFactory{
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if (orderType.equals("cheese")) {
            pizza = new LDChessPizza();
        } else if (orderType.equals("pepper")) {
            pizza = new LDPepperPizza();
        }
        return pizza;
    }
}
  • OrderPizza
public class OrderPizza {
    AbsFactory absFactory;
    public OrderPizza(AbsFactory absFactory) {
        setAbsFactory(absFactory);
    }
    private void setAbsFactory(AbsFactory absFactory) {
        //...获取pizza类型
    }
}

源码

  • Calendar,使用了简单工厂模式
Calendar cal = Calendar.getInstance();
System.out.println("年:" + cal.get(Calendar.YEAR));
//月份从0开始,要+1
System.out.println("月:" + (cal.get(Calendar.MONTH) + 1));
System.out.println("日:" + cal.get(Calendar.DAY_OF_MONTH));
System.out.println("时:" + cal.get(Calendar.HOUR_OF_DAY));
System.out.println("分:" + cal.get(Calendar.MINUTE));
System.out.println("秒:" + cal.get(Calendar.SECOND));
  • getInstance,静态方法,根据时区和地区返回实例
public static Calendar getInstance()
{
    return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}
  • createCalendar,根据aLocale不同,返回不同的实例 image.png image.png

小结

  • 将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦
  • 创建对象实例时,不要直接new对象,把这个new类的动作放在一个工厂方法里,并返回,变量不要直接持有具体类的引用
  • 不要让类继承具体的类,而是让类继承抽象类或者实现接口
  • 不要覆盖基类中已经实现的方法