1工厂模式
1.1.简单工厂模式
需求 要便于披萨种类的扩展,要便于维护
披萨的种类很多(比如 GreekPizz、CheessPizz等)
披萨的制作又prepare,bake,cut,box
完成披萨店订购功能。
传统模式
以点披萨代码为例
public OrderPizza() {
Pizza pizza = null;
String orderType;// 订购披萨的类型
do {
orderType = getType();
if (orderType.equals("greek")) {
pizza = new GreekPizza();
pizza.setName("希腊披萨");
}else if (orderType.equals("cheese")) {
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
}else if (orderType.equals("pepper")) {
pizza = new PepperPizza();
pizza.setName("胡椒披萨");
}else {
break;
}
// 输出pizza制作过程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while (true);
}
假如有新的Pizza种类就需要在上方加else if,此时是直接让调用者直接去创建披萨的对象。
传统方式的优缺点
1.优点是比较好理解,简单易操作
2.缺点是违反了设计模式的OCP原则,既对扩展开放,对修改关闭,既当我们给类增加新功能的时候,尽量不修改代码,或者尽可能少的修改代码
改进思路:把创建Pizza对象封装到一个类中,这样有新的Pizza种类时,只需要修改该类就可,其他有创建到Pizza对象的代码就不需要修改了。->简单工厂模式
上面的例子中运用上面的思想我们把原来的orderPizza放在工厂类来实现
public class SimpleFactory {
// 根据OrderType返回对应的Pizza对象
public Pizza createPizza(String orderType) {
Pizza pizza = null;
System.out.println("使用简单工厂模式 = " + orderType);
if (orderType.equals("greek")) {
pizza = new GreekPizza();
pizza.setName("希腊披萨");
}else if (orderType.equals("cheese")) {
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
}else if (orderType.equals("pepper")) {
pizza = new PepperPizza();
pizza.setName("胡椒披萨");
}
return pizza;
}
}
对比传统模式和简单工厂模式的类图可以看出来,在OrderPizza和Pizza中间又加了一层,原来是OrderPizza依赖Pizza,后来让SampleFactory依赖Pizza。 通过封装SimpleFactory这个类,我们将OrderPizza和Pizza进行了解耦合。
不过除了对象创建在简单工厂里创建 其他工作还是在OrderPizza中进行
public class OrderPizza {
// 定义一个简单工厂对象
SimpleFactory simpleFactory;
Pizza pizza = null;
// 构造器
public OrderPizza(SimpleFactory simpleFactory){
setFactory(simpleFactory);
}
public void setFactory(SimpleFactory simpleFactory) {
String orderType = "";// 用户输入的
this.simpleFactory = simpleFactory;//设置简单工厂对象
do {
orderType = getType();
pizza = this.simpleFactory.createPizza(orderType);
// 输出Pizza
if (pizza != null) {// 订购成功
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} else {
System.out.println("订购披萨失败");
break;
}
} while (true);
}
// 写一个方法,可以获取客户希望订购的披萨种类
private String getType() {
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza type:");
return bufferedReader.readLine();
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
}
基本介绍
简单工厂模式时属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式
简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)
在软件开发中,当我们会用到大量的创建某种,某类或者某批对象时,就会使用到工厂模式
简单工厂模式也叫静态工厂模式
1.2.工厂方法模式
需求 披萨项目新的需求:客户在北京点披萨时,可以点不同口味的披萨,比如北京的奶酪pizza、北京的胡椒pizza或者时伦敦的奶酪pizza、伦敦的胡椒pizza。
思路:使用简单工厂模式,创建不同的简单工厂类,比如BJPizzaSimpleFactory、LDPizzaSimpleFactory、等等。从当前这个案例来说,也是可以的,但是考虑到项目的规模以及软件的可维护性、可扩展性并不是特别好
思路2 使用工厂方法模式
基本介绍
工厂方法模式设计方案:将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐子类中具体实现。
工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类
定义抽象类
public abstract class OrderPizza {
// 定义一个抽象方法,createPizza 让各个工厂子类自己实现
abstract Pizza createPizza(String orderType);
// 构造器
public OrderPizza() {
Pizza pizza;
String orderType = "";// 用户输入的
do {
orderType = getType();
pizza = createPizza(orderType);// 抽象方法,由工厂子类来完成
// 输出Pizza
if (pizza != null) {// 订购成功
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} else {
System.out.println("订购披萨失败");
break;
}
} while (true);
}
// 写一个方法,可以获取客户希望订购的披萨种类
private String getType() {
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza type:");
return bufferedReader.readLine();
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
}
具体工厂
public class BJOrderPizza extends OrderPizza {
@Override
Pizza createPizza(String orderType) {
Pizza pizza = null;
if (orderType.equals("cheese")) {
pizza = new BJCheesePizza();
}else if (orderType.equals("pepper")) {
pizza = new BJCheesePizza();
}
return pizza;
}
}
public class LDOrderPizza extends OrderPizza {
@Override
Pizza createPizza(String orderType) {
Pizza pizza = null;
if (orderType.equals("cheese")) {
pizza = new LDCheesePizza();
}else if (orderType.equals("pepper")) {
pizza = new LDCheesePizza();
}
return pizza;
}
}
工厂方法将对象的实例化推迟到了子类,怎么理解呢? 之前的SimpleFactory在createPizza中直接就new出来了,但是在工厂方法中,我们将createPizza这个动作推迟到了OrderPizza的子类(XXOrderPizza)中才完成. 原来是由一个对象(SimpleFactory)负责所有具体类的实例化,现在实例化Pizza的责任被移到一个抽象类的子类中,此方法就如同一个工厂,所以我个人更喜欢称它为方法工厂。
1.3.抽象工厂模式
基本介绍
抽象工厂模式:定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类
抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。
创建一个抽象工厂
// 一个抽象工厂模式的抽象层(接口)
public interface AbsFactory {
// 让下面的工厂子类来具体实现
Pizza createPizza(String orderType);
}
子工厂实现抽象工厂
// 这是一个工厂子类
public class BJFactory implements AbsFactory {
@Override
public Pizza createPizza(String orderType) {
System.out.println("使用的是抽象工厂模式~~~~");
Pizza pizza = null;
if (orderType.equals("cheese")) {
pizza = new BJCheesePizza();
} else if (orderType.equals("pepper")) {
pizza = new BJPepperPizza();
}
return pizza;
}
}
public class LDFactory implements AbsFactory {
@Override
public Pizza createPizza(String orderType) {
System.out.println("使用的是抽象工厂模式~~~~");
Pizza pizza = null;
if (orderType.equals("cheese")) {
pizza = new LDCheesePizza();
} else if (orderType.equals("pepper")) {
pizza = new LDPepperPizza();
}
return pizza;
}
}
工厂模式 在JDK-Calendar 应用的源码分析 简单工厂模式
public static void main(String[] args) {
Calendar cale = Calendar.getInstance();
int year = cale.get(Calendar.YEAR);
int month = cale.get(Calendar.MONTH) + 1;
int day = cale.get(Calendar.DATE);
int hour = cale.get(Calendar.HOUR_OF_DAY);
int minute = cale.get(Calendar.MINUTE);
int second = cale.get(Calendar.SECOND);
System.out.println("Year: " + year);
System.out.println("Month: " + month);
System.out.println("Day: " + day);
System.out.println("Hour: " + hour);
System.out.println("Minute: " + minute);
System.out.println("Second: " + second);
}
如图
工厂模式小结
创建对象实例时,不要直接new类,而是把这个new类的动作放在一个工厂的方法中,并返回。有的书上说,变量不要直接持有具体类的引用。
不要让类继承具体类,而是继承抽象类或者是实现interface接口
不要覆盖基类中已经实现的方法。