《Head First设计模式》笔记整理...欢迎交流...

定义

定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

OO原则

  • 封装变化
  • 多用组合少用继承
  • 针对接口变成,不针对实现编程
  • 为交互对象之间的松耦合设计而努力
  • 类应该对扩展开放,对修改关闭
  • 要依赖抽象,不要依赖具体类

类图

图片描述

正如在正式定义中所说的,常常听到其他开发人员说,工厂方法让子类决定要实例化的类是哪一个。希望不要理解错误,所谓的“决定”,并不是指模式允许子类本身在运行时做决定,而是指在编写创建者类时,不需要知道实际创建的具体产品是哪一个。选择使用哪个产品的子类,自然就决定看实际创建的产品是什么。

依赖倒置原则

要依赖抽象,不要依赖具体类。

这个原则听起来很像“针对接口编程,不针对实现编程”。然而,这里更强调“抽象”。这个原则说明了不能让高层组件依赖低层组件,“两者”都应该依赖抽象。

clipboard.png

几个方法帮助你遵循此原则......

  • 变量不可以持有具体类的引用
  • 不要让类派生自具体类
  • 不要覆盖积累中已经实现的方法

如果覆盖基类已经实现的方法,那么你的基类不是一个真正适合被继承的抽象。基类中已经实现的方法,应该由所有的子类共享。

需要注意的是,所有的原则都是为了更好的设计,并不是必须随时都遵循的。

创建一个pizza工厂

public abstract class PizzaStore {
    public Pizza orderPizza(String type) {
        Pizza pizza;
        
        pizza = ceratePizza(type);
        
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        
        return pizza;
    }
    
    public abstract Pizza createPizza(String type);
    
    //其它方法
}


public class NYPizzaStore extends PizzaStore {
    Pizza createPizza(String item) {
        if(item.eauals(cheese)) {
            return new NYStyleCheesePizza();
        } else if() {
            ...
        }
    }
}
//工厂方法是抽象的,所以必须依赖子类来处理对象的创建
//工厂方法必须返回一个产品
//工厂方法将客户,和实际创建具体产品的代码分隔开来
//工厂方法可能需要传递参数(也可能不需要)来指定所需要的产品

abstract Product factoryMethod(String type)
public abstract class Pizza {
    String name;
    String dough;
    String sauce;
    ArrayList topppings = new ArrayList();
    
    void prepare() {
        
        ...
        
        for(int i = 0; i < topppings.size(); i++) {
            System.out.printIn("  " + topppings.get(i)); //准备工作要以特定的顺序进行,有一道连串的步骤
        }
    };
    
    void brake() { ... };
    
    void cut() { ... };
    
    void box() { ... };
    
    Public String getName() {
        return name;
    };
}

public NYStyleCheesePizza extends Pizza {
    public NYStyleCheesePizza() {
        name = "NY Style Suace and Cheese Pizza";
        dough = "Thin Crust Dough";
        sauce = "Marinara Sauce";
        
        topppings.add("Grated Reggiao Cheese");
    }
}

测试

public class PizzaTestDrive {
    public static void main() {
        PizzaStore nyStore = NyPizzaStore();
        Pizza pizza = nyStore.orderPizza("cheese");
        
        System.out.printIn("Ethan ordered a " + pizza.getName() + "\n");
        // Ethan ordered a NY Style Suace and Cheese Pizza
    }
}

抽象工厂模式

抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不许奥明确指定具体类。

抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道(或关心)实际产出的产品是什么。这样依赖,客户就从具体产品中被解耦。

再回到披萨店

上面披萨店的设计已经很棒了,但是对不同地区的加盟店,,原料是不一样的(如,纽约的红酱料和芝加哥的酱料是不一样的),但是流程是一致。如何解耦?创建一个原料工厂。

public class NYPizzaStore extends PizzaStore {
    protected Pizza createPizza(Stirng item) {
        Pizza pizza = null;
        PizzaIngredientFactory ingredientFactory = new PizzaIngredientFactory();
    }
    
    if(item.equals("cheese")) {
        pizza = new cheesePizza(ingredientFactory);
        pizza.setName("new You Style Cheese Pizza");
    } else if (...) { ... }
    
    return pizza;
}

public abstract class Pizza {
    String name;
    Dough dough;
    Sauce sauce;
    Veggies veggies();
    chenegie veggues;
    Cheese cheeese;
    Perperroni pepperoni;
    clams clams;
    
    abstract void Prepare();
    
    void bake() { ... }
    
    void cut() { ... }
    
    void box() { ... }
    
    void setName(String name) {}
    
    void setName() {}
}

public class CheesePizza extends Pizza {
    PizzaIngredientFactory ingredientFactory;
    
    public CheesePizza(PizzaIngredientFactory ingredientFactory) {
        this.ingredientFactory = ingredientFactory;
    }
    
    void prepare() {
        dough = ingredientFactory.createDough();
        sauce = ingredientFactory.createSauce();
        cheese = ingredientFactory.createCheese();
    }
}

大米aBigRice
236 声望24 粉丝

欢迎我呀~