设计模式---工厂模式



工厂模式:

当代码中有很多具体类的创建,可能就有问题。像下面这段代码,就有很多实例创建,当哪天需要修改,就要改动源码。这对代码的维护和更新代价较大。

Duck duck;

if (pinic) {
	duck = new MallardDuck();
} else if (hunting) {
	duck = new DecoyDuck();
} else if (inBathTub) {
	duck = new RubberDuck();
}

所以还是那句话,要把改变的代码封装起来。

下面举个例子:

假如你有一家匹萨店,代码如下:

Pizza orderPizza() {
	Pizza pizza = new Pizza();
	pizza.prepare();
	pizza.bake();
	pizza.cut();
	pizza.box();
	return pizza;
}

但是当你需要增加更多匹萨类型时:

Pizza orderPizza(String type) {
	Pizza pizza;
	//根据不同类型创建不同pizza
	if (type.equals("cheese")) {
		pizza = new CheesePizza();
	} else if (type.equals("greek")) {
		pizza = new GreekPizza();
	} else if (type.equals("pepperoni")) {
		pizza = new PepperoniPizza();
	}
	
	pizza.prepare();
	pizza.bake();
	pizza.cut();
	pizza.box();
	return pizza;
}

很明显当我们需要改变pizza的时候会比较麻烦,需要改变的代码比较多。所以我们必须把变的代码封装起来,就是创建pizza的那部分代码。

简单工厂

所谓工厂就是创建对象。我们可以新建一个SimplePizzaFactory。当需要对象的时候,我们可以从这个工厂中获取。

public class SimplePizzaFactory {
	public Pizza createPizza(String type) {
		Pizza pizza = null;
		if (type.equals("cheese")) {
			pizza = new CheesePizza();
		} else if(type.equals("peppernoi")) {
			pizza = new PepperoniPizza();
		} else if (type.equals("clam")) {
			pizza = new ClamPizza()
		} else if (type.equals("veggie")) {
			pizza = new VeggiePizza();
		}
		return pizza;
	}
}

这个时候我们的PizzaStore也需要改变下:

public class PizzaStore {
	SimplePizzaFactory factory;
	
	public PizzaStore(SimplePizzaFactory factory) {
		this.factory = factory;
	}
	Pizza orderPizza(String type) {
		Pizza pizza;
		pizza = factory.createPizza(type);
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}
}

这就是简单工厂,其实这不算一种设计模式,算一种编程习惯而已

工厂方法

但是简单工厂好像破坏了原有的框架结构,但是不用简单工厂,在PiazzaStore里面创建匹萨又非常麻烦有没有一个比较好的设计模式?

我们可以在PizzaStore增加一个abstract 方法。然后每一个区域都创建一个PizzaStore的子类,来实现自己区域风格的pizza。

public abstract class PizzaStore {

	Pizza orderPizza(String type) {
		Pizza pizza;
		pizza = createPizza(type);
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}
	abstract Pizza createPizza(String type);//抽象方法需要在每个子类中实现
}

在每个子类中实现createPizza方法,然后创建不同的Pizza。

这样框架有了,代码也解耦了。

public class NYPizzaStore extends PizzaStore {
	Pizza createPizza(String type) {
		Pizza pizza = null;
		if (type.equals("cheese")) {
			pizza = new NYStyleCheesePizza();
		} else if(type.equals("peppernoi")) {
			pizza = new NYStylePepperoniPizza();
		} else if (type.equals("clam")) {
			pizza = new NYStyleClamPizza()
		} else if (type.equals("veggie")) {
			pizza = new NYStyleVeggiePizza();
		}
		return pizza;
	}
}

工厂方法用来处理对象的创建,并将这样的行为封装在子类中。这样,客户程序关于父类的代码和子类对象创建代码就解耦了。

abstract Product factoryMethod(String type)

具体调用如下:

PizzaStore npPizzaStore = new NYPizzaStore();
npPizzaStore.orderPizza("cheese");

然后就会调用子类的createPizza创建Pizza,接着就会

		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();

我们再来看下Pizza类:

public abstract class Pizza {
	String name;
	String dough;
	String sauce;
	ArrayList toppings = new ArrayList();
	void prepare() {
		System.out.println("preareing " + name);
	}
	
	void bake () {
		System.out.println("bake for 25 minutes");
	}
	void cut() {
		System.out.println("cutting the pizza into diagonal slices")
	}
	void box() {
		System.out.println("box")
	}
	public String getName() {
		return name;
	}
}

public class ChicagoStyleCheesePizza extends Pizza {
	public ChicageStyleCheesePizza() {
		name = "Chicago Pizza";
		dough = "Crust Dough";
		sauce = "Plum tomato Sauce";
		toppings.add("cheese");
	}
	void cut {
		System.put.println("Cutting the pizza into square slices");
	}
}

定义工厂方法:

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

抽象工厂

现在又有新需要了,各区域使用一些自己的原料。

工厂接口:

public interface PizzaIngredientFactory {
	public Dough createDough();
	public Sauce createDough();
	public Cheese createCheese();
	public Veggies[] createVeggies();
	public Pepperoni createPepperoni();
	public Clams createClam();
}

具体的工厂如下:

public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
	public Dough createDough() {
		return new ThinCrustDough();
	}
	public Sauce createSauce() {
		return new MarinaraSauce();
	}
	public Cheese createCheese {
		return new ReggianoCheese();
	}
	public Veggies[] createVeggies() {
		Veggies veggies[] = {new Garlic(), new Onion(), new Mushroom(), new RedPerpper() };
	}
	public Pepperoni createPepperoni() {
		return new SlicedPepperoni();
	}
	public Clams createClam() {
		return new FreshClams();
	}
}

再来看看抽象Pizza类,主要把perpare方法变成抽象的,并且在子类的这个方法中,收集我们需要的原料。

public abstract class Pizza {
	String name;
	String dough;
	String sauce;
	Veggies veggies[];
	Cheese cheese;
	Pepperoni peppernoi;
	Clams clam;
	abstract void prepare() {};
	
	void bake () {
		System.out.println("bake for 25 minutes");
	}
	void cut() {
		System.out.println("cutting the pizza into diagonal slices")
	}
	void box() {
		System.out.println("box")
	}
	public String setName(String name) {
		this.name = name
	}
	public String getName() {
		return name;
	}
	public String toString() {
	}
}

我们再来看下具体Pizza的子类实现,利用工厂创建一系列原料。

public class CheesePizza extends Pizza {
	PizzaIngredientFactory ingredientFactory;
	public CheesePizza(PizzaIngredientFactory ingredientFactory) {
		this.ingredientFactory = ingredientFactory;
	}
	void prepare() {
		System.out.println("preparing " +name);
		dough = ingredientFactory.createDough();
		sauce = ingredientFactory.createSauce();
		cheese = ingredientFactory.createCheese();
	}
}

再来看PizzaStore的子类:

public class NYPizzaStore extends PizzaStore {
	Pizza createPizza(String type) {
		Pizza pizza = null;
		PizzaIngredientFactory ingredientFactory =
			new NYPizzaIngredientFactory();
		if (type.equals("cheese")) {
			pizza = new CheesePizza(ingredientFactory);
			pizza.setName("new York Style Cheese pizza")
		} else if(type.equals("peppernoi")) {
			pizza = new PepperoniPizza(ingredientFactory);
			pizza.setName("new York Style PepperoniPizza")
		} else if (type.equals("clam")) {
			pizza = new ClamPizza(ingredientFactory)
			pizza.setName("new York Style clam pizza")
		} else if (type.equals("veggie")) {
			pizza = new VeggiePizza(ingredientFactory);
			pizza.setName("new York Style veggie pizza")
		}
		return pizza;
	}
}

抽象工厂模式定义:

提供一个接口,用于创建相关或依赖对象的家族,而不需要指定具体类。

这里的这个例子 ,抽象工厂是在工厂方法中的。
























猜你喜欢

转载自blog.csdn.net/qq_40182703/article/details/80600559