Object-Oriented Programming Java)
• Object-Oriented Programming (Java)
Design pattern Factory工厂模式 Decorator装饰者模式 Observer观察者模式
Design Pattern 1 Factory 工厂模式 2 Decorator 装饰者模式 3 Observer 观察者模式
NeW的危害 当看到“New”时,就会想到“具体”: 是的,当使用“New”时,你的确是在实例化一个具体类,所以用的确实是实 现,而不是接口。这是一个问题,你已经知道了代码绑着具体类会导致代码更脆弱, 更缺乏弹性。 Duck duck-new Mallardducko: 要使用接口,让代 但是还是得建立具 码更有弹性 体类的实例 当有一群相关的具体类时,通常会写出这样的代码: Duckduck if(picnic)i 线你同登变化和扩展, duck =new Mallardduck 0: 锰狱利說褽被重新打开进行 3 else if(hunting) t duck =new Decoy DuckO 修改。使系统维护变得困难。 3 else if(in Bathtub) 向对象一个重要原则:对扩 duck =new RubberDuckO 展开放,对修改封闭
New的危害 当看到“New”时,就会想到“具体”: 是的,当使用“New”时,你的确是在实例化一个具体类,所以用的确实是实 现,而不是接口。这是一个问题,你已经知道了代码绑着具体类会导致代码更脆弱, 更缺乏弹性。 Duck duck=new MallardDuck(); 要使用接口,让代 码更有弹性 但是还是得建立具 体类的实例 当有一群相关的具体类时,通常会写出这样的代码: Duck duck; if(picnic) { duck =new MallardDuck(); } else if(hunting) { duck =new DecoyDuck(); } else if(inBathTub) { duck =new RubberDuck(); } 有一大堆不同的鸭子类, 必须要等到运行时,才 知道例化哪一个 也就是说,一旦有变化和扩展, 这段代码就要被重新打开进行 修改。使系统维护变得困难。 面向对象一个重要原则:对扩 展开放,对修改封闭
Let s start from an example 假如你有一个比萨店,身为对象村内最先进的萨店的主人,你 的代码可能这么写: Pizza OrderPizza( i Pizza pizza =new Pizza pizza. prepared 为了让系统更有弹性,我们很 希望这是一个抽象类或接口。 pizza. bakeo 但如果这样,这些类或接口就 pizza. cuto 无法真接实例化。 pizza. boxo return pizza
Let’s start from an example 假如你有一个比萨店,身为对象村内最先进的萨店的主人,你 的代码可能这么写: 为了让系统更有弹性,我们很 希望这是一个抽象类或接口。 但如果这样,这些类或接口就 无法真接实例化。 Pizza OrderPizza() { Pizza pizza =new Pizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; }
事情往往很复杂 但是你需要更多的比萨类型 所以必须要增加一些代码,来“决定”适合的比萨类型,然后再“制造”这个比萨: Pizza orderPizza( String type Pizza pizza 现在把比萨类型号传入 orderPizza(0。 if (type equals("cheese"))I pizza =new CheesePizzao 3 else if (type equals(greek") 根据比萨的类型,我们实例化正确的 pizza =new GreekPizzao 具体类,然后将其赋值为 pizza实例变 y else if 量。请注意,这里的任何比萨都必须 (type equals(pepperoni)t 实现pza接口。 pizza=new Pepperonipizzao pizza. prepared pizza. bakeo 日我们有了一个比萨,需要 pizza. cutO 做一些准务(就是擀揉面皮、 pizza. boXO 加上佐料,例如芝士),然后 return pIzza 烧烤、切片、装盒!
事情往往很复杂 但是你需要更多的比萨类型: 所以必须要增加一些代码,来“决定”适合的比萨类型,然后再“制造”这个比萨: Pizza orderPizza( ) { Pizza pizza; pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; 现在把比萨类型号传入orderPizza()。 根据比萨的类型,我们实例化正确的 具体类,然后将其赋值为pizza实例变 量。请注意,这里的任何比萨都必须 实现pizza接口。 一旦我们有了一个比萨,需要 做一些准务(就是擀揉面皮、 加上佐料,例如芝士),然后 烧烤、切片、装盒! String type if (type.equals("cheese")) { pizza =new CheesePizza(); } else if (type.equals("greek")) { pizza =new GreekPizza(); } else if (type.equals("pepperoni")) { pizza=new PepperoniPizza(); }
问题的根源 但是压力来自于增加更多的比萨类型 你发现你所有的竞争者都已经在他们的菜单中加入了一些流行风味的比萨: Clam Pizza(蛤蜊比 萨)、 Veggie Pizza(素食比萨)。很明显,你必须要赶上他们,所以也要把这些风味加进你的菜单 中。而最近 Greek pizza(希腊比萨)卖得不好,所以你决定将它从菜单中去掉: Pizza orderPizza(String type)( P区 za pizza if(type equals("cheese" )i pizza =new CheesePizza0 helse if (type equal greek)i 这是变化的部分。 此代码“没有”对修 pizza =new GreekPizzaf; 随着时间过去, 改封闭。如果比萨店 }elei( ype. equal(" pepperoni){比萨菜单改变, 改变它所供应的比萨 pizza snew Pepperonipizzao 这里就必须一改 风味,就得进到这里 } else if( (type equal(“cam”)){ 再改。 来修改。 pizza =new ClamPizza(; } else if{type.equa(“ veggie” pizza =new VeggiePizza0 pizza. prepare 这里是我们不想改变的地方,因 pizza. bake 0; 为比萨的准备、烘烤、包装、多 pizza. cut( 年来都保持不变,所以这部分代 pizza. boxO 码不会改变,只有发生这些动作 return pizza; 的比萨会改变
问题的根源 但是压力来自于增加更多的比萨类型 你发现你所有的竞争者都已经在他们的菜单中加入了一些流行风味的比萨:Clam Pizza(蛤蜊比 萨)、Veggie Pizza(素食比萨)。很明显,你必须要赶上他们,所以也要把这些风味加进你的菜单 中。而最近Greek Pizza(希腊比萨)卖得不好,所以你决定将它从菜单中去掉: Pizza orderPizza(String type) { Pizza pizza; if (type.equals("cheese")) { pizza =new CheesePizza(); } else if (type.equal("greek")) { pizza =new GreekPizza(); } else if (type.equal("pepperoni")) { pizza =new PepperoniPizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; 此代码“没有”对修 改封闭。如果比萨店 改变它所供应的比萨 风味,就得进到这里 来修改。 这是变化的部分。 随着时间过去, 比萨菜单改变, 这里就必须一改 } else if (type.equal(“Clam”)) { 再改。 pizza =new ClamPizza(); } else if (type.equal(“veggie”)){ pizza =new VeggiePizza(); } 这里是我们不想改变的地方,因 为比萨的准备、烘烤、包装、多 年来都保持不变,所以这部分代 码不会改变,只有发生这些动作 的比萨会改变
工厂模式出现了 封装创建对象的代码 现在最好将创建对象移到 orderPizza(之外,但怎么做呢,这个嘛,要把创建比萨的代 码移到另一个对象中,由这个新对象专职创建比萨 Pizza orderPizza( string type)t izza snew cheesepizz pizza =new GreekPizza(: Pizza pizza; else if (type equal("pepperoni pizza=new Pe ppe else if(ty pe equal("Clam"))[ 首先,把创建对象的代码 else if(ty pe equal("veggie"))( pizza=new Veggie Pizza( 从 orderPizz20方法中抽离 pizza. prepare pizza. bakeo pizza. cutO pizza. boXO return pizza 然后把这部分的代码搬 到另一个对象中,这个 新对象只管如何创建比 萨,如果任何对象想要 创建比萨,找它就对了
工厂模式出现了 封装创建对象的代码 现在最好将创建对象移到orderPizza()之外,但怎么做呢,这个嘛,要把创建比萨的代 码移到另一个对象中,由这个新对象专职创建比萨。 if (type.equals("cheese")) { pizza =new CheesePizza(); } else if (type.equal("greek")) { pizza =new GreekPizza(); } else if (type.equal(“pepperoni”)) { pizza =new PepperoniPizza(); } else if (type.equal("Clam")) { pizza =new ClamPizza(); } else if (type.equal("veggie")) { pizza =new VeggiePizza(); } Pizza orderPizza(String type) { Pizza pizza; pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } 然后把这部分的代码搬 到另一个对象中,这个 新对象只管如何创建比 萨,如果任何对象想要 创建比萨,找它就对了
解读工厂模式 工厂( factory)处理创建对象的细节。一旦有了 SimplePizzaFactory, orderPizz2a(就变成此对象的客户。当需要 比萨时,就叫比萨工厂做一个。那些 order Pizza0方法需要知道希 腊比萨或者蛤蜊比萨的日子一去不复返了。现在 order Pizza(方法 只关心从工厂得到了一个比萨,而这个比萨实现了Pz2a接口,所 以它可以调用 prepare()、bake0、cutO|、box()来分别进行准备、 烘烤、切片、装盒。 工厂模式的目的: Define an interface for creating an object, but let subclasses decide which class to instantiate Factor Method lets a class defer instantiation to subclasses
解读工厂模式 工厂(factory)处理创建对象的细节。一旦有了 SimplePizzaFactory,orderPizza()就变成此对象的客户。当需要 比萨时,就叫比萨工厂做一个。那些orderPizza()方法需要知道希 腊比萨或者蛤蜊比萨的日子一去不复返了。现在orderPizza()方法 只关心从工厂得到了一个比萨,而这个比萨实现了Pizza接口,所 以它可以调用prepare()、bake()、cut()|、box()来分别进行准备、 烘烤、切片、装盒。 工厂模式的目的: Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses
建立一个简单的工厂 先从工厂本身开始。我们要定义一个类,为所有比蓝封创建对 象的代码。代码像这样 SimplePizzaFactory是我们的 public class simplePizzaFactory t 新类,它只做一件事,帮它的 客户创建比萨。 i public Pizza createPizza(String type) Pizza pizza =null 首先,在这个工厂内定义一个 createPizza()方法。所有客户 if (type equals("cheese))( 用这个方法来实例化新对象 pizza =new CheesePizza(; 3 else if(tyl pe equals(" pepperoni"){这是从 orderPizza0方 pizza =new Pepperonipizza( 法中移过来的代码。这 个代码没什么变动,和 3 else if(type equals clam))i 原本 orderPizza(方法 pizza =new ClamPlzzao 中的代码一样,依然是 3 else if(type equals("veggie")i 以比萨的类型为参数。 pizza =new veggiePizza(; return pizza
建立一个简单的工厂 先从工厂本身开始。我们要定义一个类,为所有比萨封装创建对 象的代码。代码像这样………… public class SimplePizzaFactory { { 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; 这是从orderPizza()方 法中移过来的代码。这 个代码没什么变动,和 原本orderPizza()方法 中的代码一样,依然是 以比萨的类型为参数。 public Pizza createPizza(String type) Pizza pizza =null; SimplePizzaFactory是我们的 新类,它只做一件事,帮它的 客户创建比萨
重建我们的披萨店By工厂模式 创建比萨,要做这样的改变: 为 Pizza store加上一个对 public class PizzaStore SimplePizzaFactory的引用。 SimplePizzaFactory factory public PizzaStore(simplePizzaFactory factory)I this factory=factory; Pizza store的构造器 需要一个工厂作为参数。 public Pizza orderPizza(String type)t Pizza pizza; orderPizz20方法通过简单传入订 pizza =factory. createPizza(type); 单类型来使用工厂创建比萨。请 注意,我们把new操作符替换成 pizza. prepared 工厂对象的创建方法,这里不再 pizza. bakeo 使用具体实例化。 pizza. cuto pizza. boXo return pizza ∥这里是其他方法 注意:原先的ese不见了!
重建我们的披萨店By工厂模式 创建比萨,要做这样的改变: public class PizzaStore { } public Pizza orderPizza (String type) { Pizza pizza; pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } //这里是其他方法 } 为PizzaStore加上一个对 SimplePizzaFactory的引用。 orderPizza()方法通过简单传入订 单类型来使用工厂创建比萨。请 注意,我们把new操作符替换成 工厂对象的创建方法,这里不再 使用具体实例化。 注意:原先的if-else不见了! SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory) { this.factory=factory; PizzaStore的构造器, 需要一个工厂作为参数。 pizza =factory.createPizza(type);