100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > Head First设计模式读书笔记四 简单工厂 工厂模式 抽象工厂模式

Head First设计模式读书笔记四 简单工厂 工厂模式 抽象工厂模式

时间:2020-08-12 09:01:24

相关推荐

Head First设计模式读书笔记四 简单工厂 工厂模式 抽象工厂模式

本文示例代码材料源自Head First设计模式

以前整理自己整理的链接:

工厂模式

/u011109881/article/details/56541580

抽象工厂

/u011109881/article/details/56730497

实例

假设现在要生产各种各样的Pizza,Pizza有不同的原料,就可以做出不同的Pizza,Pizza需要经过材料准备 烘焙 切片 打包等诸多过程。

没有学习设计模式之前,我们的代码可能是这样的:

public class PizzaStore {Pizza orderPizza(String type) {Pizza pizza;switch (type) {case "cheese":pizza = new CheesePizza();break;case "greek":pizza = new GreekPizza();break;default:pizza = new CheesePizza();break;}pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;}}

public class Pizza {public void prepare(){System.out.println("prepare");};public void bake(){System.out.println("bake");};public void cut(){System.out.println("cut");};public void box(){System.out.println("box");};}

但是请思考一下,这样的代码易于扩展么?

比如我们要新加几种Pizza,原先的Pizza由于销量不好全部下架。那么我们只好进入orderPizza内部,对其进行一次“大手术”,而这违反了设计原则的对修改关闭对扩展开放的原则。

使用简单工厂(不算设计模式 只能算技巧)

我们再分析一下orderPizza的代码,可以发现生产Pizza的部分可能会经常变动,而包装过程不怎么变动。那么我们可不可以将变化的部分抽出来呢?

简单工厂类图

把变化的部分抽离出来,就是利用了简单工厂的思想。它的结构如下:

public class SimplePizzaFactory {public Pizza createPizza(String type){Pizza pizza;switch (type) {case "cheese":pizza = new CheesePizza();break;case "greek":pizza = new GreekPizza();break;default:pizza = new CheesePizza();break;}return pizza;}}

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;}}

聪明的读者也许一下子就会发现问题:这丫的不是自欺欺人掩耳盗铃么。没错,你是把变化的部分抽离了,放到了SimplePizzaFactory里面,但是这不过是把问题从一个地方转移到另一个地方么?问题仍然存在啊?

其实这样做有利于复用SimplePizzaFactory的代码,比如其他使用者需要对Pizza进行不同的加工。比如在门店购买的Pizza和饿了么送货的Pizza的处理应该不会相同。这样既分离了变化和不变的部分,又达成代码复用的目的。

在上面这个例子中PizzaStore中组合了SimplePizzaFactory对象,SimplePizzaFactory对象则组合了Pizza对象,Pizza对象又是各类Pizza的基类。简单工厂就是利用组合方式来分离变化与不变的部分的。

引入地域风情

现在,Pizza连锁店生意兴隆,风靡全国各地。比如上海苏州的Pizza会偏甜,湖南重庆的Pizza可能会放辣椒。

对于这种新加的元素,可以使用工厂模式。

使用工厂模式

类图:

(由于ProcessOn不能实现单个方法斜体,因此将抽象方法前面加上< A >表示抽象方法)

工厂模式代码实例

创建者类(creator)

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

public class CQPizzaStore extends PizzaStore{public CQPizzaStore() {}@Overridepublic Pizza createPizza(String type) {switch (type) {case "cheese":pizza = new CQCheesePizza();break;case "greek":pizza = new CQGreekPizza();break;default:pizza = new CQCheesePizza();break;}return pizza;}}

public class SHPizzaStore extends PizzaStore{public SHPizzaStore() {}@Overridepublic Pizza createPizza(String type) {switch (type) {case "cheese":pizza = new SHCheesePizza();break;case "greek":pizza = new SHGreekPizza();break;default:pizza = new SHCheesePizza();break;}return pizza;}}

产品类

public abstract class Pizza {String name;String dough;String sauce;ArrayList<String> toppings = new ArrayList<String>();public void prepare(){System.out.println("prepare "+ name);System.out.println("prepare Tossing "+dough);System.out.println("prepare Adding"+ sauce);System.out.println("prepare Adding toppings:");for(int i=0;i<toppings.size();i++){System.out.println(" "+toppings.get(i));}};public void bake(){System.out.println("bake");};public void cut(){System.out.println("cut");};public void box(){System.out.println("box");};public String getName(){return name;}}

public class CQCheesePizza extends Pizza{public CQCheesePizza(){name = "CQ Style Sauce and Cheese Pizza";dough = "Extar Thick Crust Dugh";sauce ="Plum Tomato Sauce";toppings.add("老干妈");}}

public class CQGreekPizza extends Pizza{public CQGreekPizza(){name = "CQ Style Sauce and Greek Pizza";dough = "Extar Thick Crust Dugh";sauce ="Plum Tomato Sauce";toppings.add("老干妈");}}

public class SHCheesePizza extends Pizza{public SHCheesePizza(){name = "SH Style Sauce and CHeese Pizza";dough = "Thin Crust Dugh";sauce ="Marinar Sauce";toppings.add("甜酱");}}

public class SHGreekPizza extends Pizza{public SHGreekPizza(){name = "SH Style Sauce and Greek Pizza";dough = "Thin Crust Dugh";sauce ="Marinar Sauce";toppings.add("甜酱");}}

测试类

public class Test {public static void main(String[] args) {PizzaStore store = new CQPizzaStore();CQCheesePizza cqCheese = (CQCheesePizza) store.orderPizza("cheese");System.out.println();CQGreekPizza cqGreek = (CQGreekPizza) store.orderPizza("greek");System.out.println();store = new SHPizzaStore();SHCheesePizza shCheese = (SHCheesePizza) store.orderPizza("cheese");System.out.println();SHGreekPizza shGreek = (SHGreekPizza) store.orderPizza("greek");System.out.println();}}

测试结果:

prepare CQ Style Sauce and Cheese Pizzaprepare Tossing Extar Thick Crust Dughprepare AddingPlum Tomato Sauceprepare Adding toppings:老干妈bakecutboxprepare CQ Style Sauce and Greek Pizzaprepare Tossing Extar Thick Crust Dughprepare AddingPlum Tomato Sauceprepare Adding toppings:老干妈bakecutboxprepare SH Style Sauce and CHeese Pizzaprepare Tossing Thin Crust Dughprepare AddingMarinar Sauceprepare Adding toppings:甜酱bakecutboxprepare SH Style Sauce and Greek Pizzaprepare Tossing Thin Crust Dughprepare AddingMarinar Sauceprepare Adding toppings:甜酱bakecutbox

使用抽象工厂模式

抽象工厂模式类图

代码示例

原料基类

public class Cheese {}

public class Clams {}

public class Dough {}

public class Pepperoni {}

public class Sauce {}

public class Veggies {}

原料实体类(部分略)

public class PepperyCheese extends Cheese {}

public class PepperyClam extends Clams{}

public class PepperyDough extends Dough {}

public class PepperyPepperoni extends Pepperoni {}

public class PepperySauce extends Sauce {}

public class RedPepper extends Veggies {}

原料工厂类

public interface PizzaIngedientFactory {public Dough createDough();public Clams createClams();public Cheese createCheese();public Pepperoni createPepperoni();public Sauce createSauce();public Veggies[] createVeggies();}

public class NYPizzaIngedientFactory implements PizzaIngedientFactory {@Overridepublic Dough createDough() {System.out.println("createDough");return new ThinCrustDough();}@Overridepublic Clams createClams() {System.out.println("createClams");return new FreshClam();}@Overridepublic Cheese createCheese() {System.out.println("createCheese");return new ReggianoCheese();}@Overridepublic Pepperoni createPepperoni() {System.out.println("createPepperoni");return new SlicedPepperoni();}@Overridepublic Sauce createSauce() {System.out.println("createSauce");return new MarinaraSauce();}@Overridepublic Veggies [] createVeggies() {System.out.println("createVeggies");Veggies veggies [] = {new Garlic() , new Onion(),new Mushroom(),new RedPepper()};return veggies;}}

public class CQPizzaIngedientFactory implements PizzaIngedientFactory {@Overridepublic Dough createDough() {System.out.println("createDough PepperyDough");return new PepperyDough();}@Overridepublic Clams createClams() {System.out.println("createClams PepperyClam");return new PepperyClam();}@Overridepublic Cheese createCheese() {System.out.println("createCheese PepperyCheese");return new PepperyCheese();}@Overridepublic Pepperoni createPepperoni() {System.out.println("createPepperoni PepperyPepperoni");return new PepperyPepperoni();}@Overridepublic Sauce createSauce() {System.out.println("createSauce PepperySauce");return new PepperySauce();}@Overridepublic Veggies [] createVeggies() {System.out.println("createVeggies");Veggies veggies [] = {new Garlic() , new Onion(),new Mushroom(),new RedPepper()};return veggies;}}

Pizza类

public abstract class Pizza {String name;Dough dough;Sauce sauce;Cheese cheese;Clams clam;ArrayList<Veggies> veggies = new ArrayList<Veggies>();PizzaIngedientFactory ingedientFactory;public abstract void prepare();public void bake(){System.out.println("bake");};public void cut(){System.out.println("cut");};public void box(){System.out.println("box");};public void setName(String name){this.name = name;}public String getName(){return name;}@Overridepublic String toString() {return name;}}

public class CheesePizza extends Pizza {public CheesePizza(PizzaIngedientFactory ingedientFactory){this.ingedientFactory = ingedientFactory;}@Overridepublic void prepare() {System.out.println("Preparing "+name);dough = ingedientFactory.createDough();sauce = ingedientFactory.createSauce();cheese = ingedientFactory.createCheese();}}

public class ClamPizza extends Pizza {public ClamPizza(PizzaIngedientFactory ingedientFactory){this.ingedientFactory = ingedientFactory;}@Overridepublic void prepare() {System.out.println("Preparing "+name);dough = ingedientFactory.createDough();sauce = ingedientFactory.createSauce();cheese = ingedientFactory.createCheese();clam = ingedientFactory.createClams();}}

店铺类

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

public class CQPizzaStore extends PizzaStore{@Overridepublic Pizza createPizza(String type) {PizzaIngedientFactory cqPizzaIngedientFactory = new CQPizzaIngedientFactory();switch (type) {case "cheese":pizza = new CheesePizza(cqPizzaIngedientFactory);pizza.setName("CQ cheese Pizza");break;case "clam":pizza = new ClamPizza(cqPizzaIngedientFactory);pizza.setName("CQ clam Pizza");break;}return pizza;}}

public class NYPizzaStore extends PizzaStore{@Overridepublic Pizza createPizza(String type) {PizzaIngedientFactory nyPizzaIngedientFactory = new NYPizzaIngedientFactory();switch (type) {case "cheese":pizza = new CheesePizza(nyPizzaIngedientFactory);pizza.setName("NY cheese Pizza");break;case "clam":pizza = new ClamPizza(nyPizzaIngedientFactory);pizza.setName("NY clam Pizza");break;}return pizza;}}

测试类

public class Test {public static void main(String[] args) {PizzaStore store = new NYPizzaStore();CheesePizza nyCheesePizza = (CheesePizza) store.orderPizza("cheese");System.out.println();ClamPizza nyClamPizza = (ClamPizza) store.orderPizza("clam");System.out.println();PizzaStore store2 = new CQPizzaStore();CheesePizza cqCheesePizza = (CheesePizza) store2.orderPizza("cheese");System.out.println();ClamPizza cqClamPizza = (ClamPizza) store2.orderPizza("clam");System.out.println();}}

关于工厂模式和抽象工厂模式的区别和联系

从上述工厂模式和抽象工厂模式的UML类图来看,其实工厂模式是存在于抽象工厂模式里面的。注意看如下共通部分:

工厂模式截图

抽象工厂模式部分截图

两种模式都是通过PizzaStore来生产产品。只不过,抽象工厂模式更为复杂一些。因为,它包含了一系列的产品原料,它更适合于生产零件很多,不同搭配可以生产不同产品的情况。

另外,这两种模式都包含生产对象的方法(本例中是createPizza方法),子类只要继承并实现该方法,就可以生产对象了,因此他们都是用于生产对象的模式,只不过抽象工厂模式中间加入了一个工厂来生成对象,他们将需要产品的客户端(本例中为测试类)与实际产品(本例中是Pizza)解耦。

所以工厂模式和抽象工厂模式还是很像的,区别相对较小。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。