设计模式之创建性模式

抽象工厂模式:提供一个创建并返回一族相关示例的接口,而不需要指明它们具体的类。

生成器模式:将一个复杂对象的构建与呈现分开,以便相同的构造过程能够根据不同需要创建不同的形式。

工厂方法模式:提供一个创建一个示例的接口,但是允许子类决定实例化哪个类,即不同的子类可以实例化不同的对象。

原型模式:先实例化一个类,然后克隆或者拷贝该类来构建新的实例。可以用共有方法进一步修改这些实例。

单件模式:某个类只能有一个实例。提供一个全局访问点。(可拓展到有限个实例)

简单工厂

意图:提供一个类,由它负责根据一定的条件创建某一具体类的实例


考虑我们开了一家披萨店,客户可以通过调用orderPizza方法来订餐。

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

		return pizza;
	}

}

我们使用一个工厂来制作各种披萨,而无需关心是哪种具体的批塞,因为工厂可以根据我们传进去的参数自己判断制造何种披萨。

public class SimplePizzaFactory {

	public Pizza createPizza(String type) {
		Pizza pizza = null;

		if (type.equals("cheese")) {
			pizza = new CheesePizza();
		} else if (type.equals("pepperoni")) {
			pizza = new PepperoniPizza();
		} else if (type.equals("clam")) {
			pizza = new ClamPizza();
		} else if (type.equals("veggie")) {
			pizza = new VeggiePizza();
		}
		return pizza;
	}
}

抽象类Pizza的定义如下:

public abstract class Pizza {
	String name;
	String dough;
	String sauce;
	ArrayList toppings = new ArrayList();
 
	void prepare() {
		System.out.println("Preparing " + name);
		System.out.println("Tossing dough...");
		System.out.println("Adding sauce...");
		System.out.println("Adding toppings: ");
		for (int i = 0; i < toppings.size(); i++) {
			System.out.println("   " + toppings.get(i));
		}
	}
  
	void bake() {
		System.out.println("Bake for 25 minutes at 350");
	}
 
	void cut() {
		System.out.println("Cutting the pizza into diagonal slices");
	}
  
	void box() {
		System.out.println("Place pizza in official PizzaStore box");
	}
}


简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

角色及其职责:

  • 工厂(Creator)角色:如上图中的SimplePizzaFactory类。简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
  • 抽象(Product)角色:如上图中的Pizza抽象类。简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
  • 具体产品(Concrete Product)角色:如上图中的CheesePizza类、VeggiePizza类和ClamPizza类。简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。一般来讲它是抽象产品类的子类,实现了抽象产品类中定义的所有接口方法,也可以覆盖父类中的方法。

模式的特点:

  • 优点:简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。在这个模式中,工厂类是整个模式的关键所在。它包含必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的。有利于整个软件体系结构的优化。
  • 缺点:体现在其工厂类上,由于工厂类集中了所有实例的创建逻辑,所以"高内聚"方面做的并不好。另外,当系统中的具体产品类不断增多时,可能会出现要求工厂类也要做相应的修改,扩展性并不很好

工厂方法模式

意图定义一个用户创建对象的接口,让子类决定实例化哪一个类,工厂方法模式使一个类的实例化延迟到其子类。这里的“决定”并不是指模式允许子类在运行时刻做决定,而是指在编写创建者类(Creator)时(如编写AnOperation()方法时),不需要知道实际创建的产品是哪一个。选择了使用哪个子类,自然就决定了实际创建的产品是什么。

依然考虑我们的披萨店。现在生意很好,我们有资本去开分店了!比如我们希望去北京、杭州、济南开不同的分店,但是由于存在地区差异,每家分店可能想要提供不同风味的批塞。如果使用简单工厂,我们可以写出三种不同的工厂,分别是BeijingPizzaFactory、HangzhouPizzaFactory、JinanPizzaFactory,那就会变成下面这个样子。

SimplePizzaFactory bjFactory = new BeijingPizzaFactory();
PizzaStore bjStore = new PizzaStore(bjFactory);

SimplePizzaFactory hzFactory = new HangzhouPizzaFactory();
PizzaStore hzStore = new PizzaStore(hzFactory);

然而,分店提出来他们想要采用自创的流程:烘烤的方法有些差异、不要切片、使用其他厂商的盒子等等。如果还是采用上面的方法,就会发现,因为大家都是采用同一个“客户”(PizzaStore),所以所有的流程必然都是相同的(都是PizzaStore中实现的orderPizza方法),这样做肯定是不行了。但是我们又希望大家使用同一个框架,同时又保持一定的弹性。这时工厂方法就登场了!

这个框架就是我们定义的一个PizzaStore的抽象类,它定义了所有分店的基本流程(框架),但允许子类继承并决定具体是怎样实现的(有弹性)。

public abstract class PizzaStore {
 
	abstract Pizza createPizza(String item);
 
	public Pizza orderPizza(String type) {
		Pizza pizza = createPizza(type);
		System.out.println("--- Making a " + pizza.getName() + " ---");
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}
}

而每个分店只需继承这个类,实现自己的工厂方法,createPizza,即可。

public class BJPizzaStore extends PizzaStore {

	Pizza createPizza(String item) {
		if (item.equals("cheese")) {
			return new NYStyleCheesePizza();
		} else if (item.equals("veggie")) {
			return new NYStyleVeggiePizza();
		} else if (item.equals("clam")) {
			return new NYStyleClamPizza();
		} else if (item.equals("pepperoni")) {
			return new NYStylePepperoniPizza();
		} else return null;
	}
}

而且,每个分店还可以覆盖父类中的orderPizza方法,实现自己的创新!

除此之外,我们的披萨的种类也更多了,因为不同地区又研发出了不同口味的披萨,而且制作方法也可能发生了改变。

public class ChicagoStylePepperoniPizza extends Pizza {
	public ChicagoStylePepperoniPizza() {
		name = "Chicago Style Pepperoni Pizza";
		dough = "Extra Thick Crust Dough";
		sauce = "Plum Tomato Sauce";
 
		toppings.add("Shredded Mozzarella Cheese");
		toppings.add("Black Olives");
		toppings.add("Spinach");
		toppings.add("Eggplant");
		toppings.add("Sliced Pepperoni");
	}
 
	void cut() {
		System.out.println("Cutting the pizza into square slices");
	}
}
与简单工厂相比,它们之间的差异如下:

  • 虽然每个具体的商店(BJPizzaStore)看起来很像一个SimplePizzaFacoty,但是这里的商店是扩展自一个类,这个类中有一个抽象方法createPizza(),每个店实现自己的方法。而在简单工厂中,这个抽象方法是一个PizzaStore使用的对象。也就是说,简单工厂使用的是对象,而工厂方法使用的是方法。
  • 简单工厂把全部事情在同一个地方做完,然后工厂方法却是建立了一个框架,剩下的让子类自己搞去吧。比如orderPizza()方法提供了一般框架,以便创建披萨,orderPizza()依赖工厂方法创建具体的类。


总结一下工厂方法。

  • Creator是一个抽象类,它实现了所有操纵产品的方法
  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值