1.1.简单工厂模式
- 需求
看一个披萨的项目:要便于披萨种类的扩展,要便于维护- 披萨的种类很多(比如 GreekPizza、CheesePizza 等)
- 披萨的制作有 prepare,bake, cut, box
- 完成披萨店订购功能。
普通实现方法:
pizza抽象类:
/**
* Description:pizza 两种pizza的抽象类
*
* @date : 2021-10-15
**/
public abstract class Pizza {
protected String name;
//不同pizza 准备的材料不同,因此写为抽象方法
public abstract void prepare();
//烘烤
public void bake() {
System.out.println(name + " baking;");
}
//切割
public void cut() {
System.out.println(name + " cutting;");
}
//打包
public void box() {
System.out.println(name + " boxing;");
}
public void setName(String name) {
this.name = name;
}
}
希腊pizza:
public class GreekPizza extends Pizza{
@Override
public void prepare() {
setName("希腊pizza");
System.out.println("给希腊pizza准备材料~~");
}
}
奶油pizza:
public class CheesePizza extends Pizza{
@Override
public void prepare() {
setName("奶酪pizza");
System.out.println("给奶油pizza准备材料~~");
}
}
OrderPizza类,获取订单信息,根据订单制作pizza:
/**
* Description:获取订单信息,根据订单制作pizza
*
* @date : 2021-10-15
**/
public class OrderPizza {
Scanner scanner = new Scanner(System.in);
public OrderPizza(){
Pizza pizza = null;
String orderTpe;
do{
orderTpe = getType();
if (orderTpe.equals("greek")){
pizza = new GreekPizza();
}else if (orderTpe.equals("cheek")){
pizza = new CheesePizza();
}else {
break;
}
//制作过程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}while (true);
}
private String getType() {
System.out.println("请输入订购的pizza type(greek | cheek):");
String s = scanner.nextLine();
return s;
}
}
客户端测试,完成pizza订购任务:
/**
* Description:客户端,完成pizza订购任务
*
* @date : 2021-10-15
**/
public class PizzaStore {
public static void main(String[] args) {
OrderPizza orderPizza = new OrderPizza();
}
}
测试结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yzugKdEK-1634630440035)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1634284927943.png)]
传统的方式的优缺点:
改进的思路分析
分析:修改代码可以接受,但是如果我们在其它的地方也有创建Pizza的代码,就意味
着,也需要修改,而创建Pizza的代码,往往有多处。
思路:**把创建Pizza对象封装到一个类(工厂)**中,这样我们有新的Pizza种类时,只需要修改该
类就可,其它有创建到Pizza对象的代码就不需要修改了 -> 简单工厂模式
简单工厂模式代码示例:
/**
* Description:
*
* @date : 2021-10-19
**/
public class SimplePizzaFactory {
public Pizza createPizza(String type) {
System.out.println("使用简单工厂模式~~");
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("greek")) {
pizza = new GreekPizza();
}else
throw new RuntimeException("参数有误");
return pizza;
}
}
1.2工厂方法模式:
新的需求:
披萨项目新的需求:客户在点披萨时,可以点不同口味的披萨,比如 北京的奶酪pizza、
北京的胡椒pizza 或者是伦敦的奶酪pizza、伦敦的胡椒pizza。
**工厂方法模式设计方案:**将披萨项目的实例化功能抽象成抽象方法,在不同的口味点
餐子类中具体实现。
**工厂方法模式:**定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方
法模式将对象的实例化推迟到子类。
代码:
pizza:
public abstract class Pizza {
protected String name;
//不同pizza 准备的材料不同,因此写为抽象方法
public abstract void prepare();
//烘烤
public void bake() {
System.out.println(name + " baking;");
}
//切割
public void cut() {
System.out.println(name + " cutting;");
}
//打包
public void box() {
System.out.println(name + " boxing;");
}
public void setName(String name) {
this.name = name;
}
}
public class BJCheesePizza extends Pizza {
@Override
public void prepare() {
setName("BJ的奶酪pizza");
System.out.println("给BJ的奶油pizza准备材料~~");
}
}
public class BJPaperPizza extends Pizza {
@Override
public void prepare() {
setName("BJ的胡椒pizza");
System.out.println("给BJ的胡椒pizza准备材料~~");
}
}
public class LDCheesePizza extends Pizza {
@Override
public void prepare() {
setName("LD的奶酪pizza");
System.out.println("给LD的奶油pizza准备材料~~");
}
}
public class LDPaperPizza extends Pizza {
@Override
public void prepare() {
setName("LD的胡椒pizza");
System.out.println("给LD的胡椒pizza准备材料~~");
}
}
OrderPizza(工厂):
public abstract class OrderPizza {
//定义抽象方法,创建pizza
abstract Pizza createPizza(String orderTpe);
Scanner scanner = new Scanner(System.in);
public OrderPizza(){
Pizza pizza = null;
String orderTpe;//订购类型
do{
orderTpe = getType();
pizza = createPizza(orderTpe);//由工厂子类实现
//制作过程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}while (true);
}
private String getType() {
System.out.println("请输入订购的pizza type(cheese | paper):");
String s = scanner.nextLine();
return s;
}
}
public class BJOrderPizza extends OrderPizza{
//子类实现创建pizza的抽象方法
@Override
Pizza createPizza(String orderTpe) {
Pizza pizza = null;
if (orderTpe.equals("cheese")){
pizza = new BJCheesePizza();
}else if (orderTpe.equals("paper")){
pizza = new BJPaperPizza();
}
return pizza;
}
}
public class LDOrderPizza extends OrderPizza{
//子类实现创建pizza的抽象方法
@Override
Pizza createPizza(String orderTpe) {
Pizza pizza = null;
if (orderTpe.equals("cheese")){
pizza = new LDCheesePizza();
}else if (orderTpe.equals("paper")){
pizza = new LDCheesePizza();
}
return pizza;
}
}
PizzaStore:(客户端)
public class PizzaStore {
public static void main(String[] args) {
//根据不通的地区创建不同的工厂
Scanner scanner = new Scanner(System.in);
System.out.println("请输入您选择的地区(北京:BJ |伦敦:LD):");
String loc = scanner.nextLine();
if (loc.equals("BJ")){
new BJOrderPizza();
}else {
new LDOrderPizza();
}
}
}
1.3抽象工厂模式
基本介绍
- 抽象工厂模式:定义了一个interface用于创建相关或有依赖关系的对象簇,而无需
指明具体的类 - 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。
- 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。
- 将工厂抽象成两层,AbsFactory(抽象工厂) 和 具体实现的工厂子类。程序员可以
根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,
更利于代码的维护和扩展。
代码:
//一个抽象工厂模式的抽象层
public interface AbsFactory {
//让下面的工厂子类具体实现
Pizza createPizza(String type);
}
public class BJFactory implements AbsFactory{
@Override
public Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")){
pizza = new BJCheesePizza();
}else if (type.equals("paper")){
pizza = new BJPaperPizza();
}
return pizza;
}
}
public class LDFactory implements AbsFactory{
@Override
public Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")){
pizza = new LDCheesePizza();
}else if (type.equals("paper")){
pizza = new LDPaperPizza();
}
return pizza;
}
}
public class OrderPizza {
//聚合抽象工厂
AbsFactory absFactory;
Scanner scanner = new Scanner(System.in);
public OrderPizza(AbsFactory absFactory){
setFactory(absFactory);
}
private void setFactory(AbsFactory absFactory){
Pizza pizza=null;
String orderTpe;//订购类型
do{
orderTpe = getType();
pizza = absFactory.createPizza(orderTpe);//由工厂子类实现
//制作过程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}while (true);
}
private String getType() {
System.out.println("请输入订购的pizza type(cheese | paper):");
String s = scanner.nextLine();
return s;
}
}
public class PizzaStore {
public static void main(String[] args) {
new OrderPizza(new BJFactory());
}
}
工厂模式小结:
- 工厂模式的意义
将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的
依赖关系的解耦。从而提高项目的扩展和维护性。 - 三种工厂模式 (简单工厂模式、工厂方法模式、抽象工厂模式)
- 设计模式的依赖抽象原则
- 创建对象实例时,不要直接 new 类, 而是把这个new 类的动作放在一个工厂的方法
中,并返回。有的书上说,变量不要直接持有具体类的引用。 - 不要让类继承具体类,而是继承抽象类或者是实现interface(接口)
- 不要覆盖基类中已经实现的方法。