深入浅出设计模式之装饰者模式工厂模式
Posted 软件猫
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入浅出设计模式之装饰者模式工厂模式相关的知识,希望对你有一定的参考价值。
工厂模式转自:http://www.cnblogs.com/zhangchenliang/p/3700820.html
装饰者模式
1、星巴克咖啡的例子,它们拓展速度非常快,准备更新订单系统来合乎它们的饮料供应要求,但是遇到了类数量爆炸,设计死板,以及基类加入新的功能并不适用于所有的子类。这个时候怎么办呢? 2.也就是说,这个时候需要装饰者模式,我们以饮料为主体,然后运行时调用调料来装饰饮料。比如说,谷歌想要摩卡和奶泡深焙咖啡,那么要做的是:- 拿一个深焙咖啡对象(DarkRoast)
- 以摩卡(Mocha)对象装饰它
- 以奶炮(Whip)对象装饰它
- 调用cost()方法,并依赖委托(delegate)将调料价钱加上去
我们有HouseBlend咖啡,有DarkRoast咖啡,有Espresso,Decaf咖啡。另外,还有Millk、Mocha、Soy、Whip调料。下面我们看一下是如何将他们装饰到一起的。 Beverage
public abstract class Beverage
String description="Unknown Beverage";
public String getDescription()
return description;
public abstract double cost();
Espresso
public class Espresso extends Beverage
public Espresso()
description = "Espresso";
@Override
public double cost()
// TODO Auto-generated method stub
return 1.99;
Mocha
public class Mocha extends CodimentDecorator
private Beverage beverage;
public Mocha(Beverage beverage)
this.beverage = beverage;
@Override
public String getDescription()
// TODO Auto-generated method stub
return beverage.getDescription()+" Mocha";
@Override
public double cost()
// TODO Auto-generated method stub
return beverage.cost()+0.55;
Milk
public class Milk extends CodimentDecorator
private Beverage beverage;
public Milk(Beverage beverage)
this.beverage =beverage;
@Override
public String getDescription()
// TODO Auto-generated method stub
return beverage.getDescription()+" milk";
@Override
public double cost()
// TODO Auto-generated method stub
return beverage.cost()+ 0.89;
Main
public class Main
public static void main(String[] args)
// TODO Auto-generated method stub
Beverage b1 = new Espresso();
b1 = new Milk(b1);
b1 = new Mocha(b1);
System.out.println(b1.getDescription()+" cost:"+b1.cost());
工厂模式
工厂模式比较简单不打算自己再写一遍了,看着篇转载的吧, 已经写得很详细了。一、引子
话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰)、Bmw(宝马)、Audi(奥迪)),还雇了司机为他开车。不过,爆发户坐车时总是这样:上Benz车后跟司机说“开奔驰车!”,坐上Bmw后他说“开宝马车!”,坐上 Audi后他说“开奥迪车!”。
你一定说:这人有病!直接说开车不就行了?!而当把这个爆发户的行为放到我们程序语言中来,我们发现C语言一直是通过这种方式来坐车的!
幸运的是这种有病的现象在OO语言中可以避免了。下面以Java语言为基础来引入我们本文的主题:工厂模式!
二、简介
工厂模式主要是为创建对象提供了接口。工厂模式按照《Java与模式》中的提法分为三类:
1. 简单工厂模式(Simple Factory)
2. 工厂方法模式(Factory Method)
3. 抽象工厂模式(Abstract Factory)
这三种模式从上到下逐步抽象,并且更具一般性。还有一种分类法,就是将简单工厂模式看为工厂方法模式的一种特例,两个归为一类。两者皆可,这本为使用《Java与模式》的分类方法。
在什么样的情况下我们应该记得使用工厂模式呢?大体有两点:
1.在编码时不能预见需要创建哪种类的实例。
2.系统不应依赖于产品类实例如何被创建、组合和表达的细节
工厂模式能给我们的OOD、OOP带来哪些好处呢??
三、简单工厂模式
这个模式本身很简单而且使用在业务较简单的情况下。一般用于小项目或者具体产品很少扩展的情况(这样工厂类才不用经常更改)。
它由三种角色组成:
工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,根据逻辑不同,产生具体的工厂产品。如例子中的Driver类。
抽象产品角色:它一般是具体产品继承的父类或者实现的接口。由接口或者抽象类来实现。如例中的Car接口。
具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现,如例子中的Benz、Bmw类。
来用类图来清晰的表示下的它们之间的关系:
下面就来给那个暴发户治病:在使用了简单工厂模式后,现在暴发户只需要坐在车里对司机说句:“开车”就可以了。来看看怎么用代码实现的:(为方便起见,所有的类放在一个文件中,故有一个类被声明为public)
- //抽象产品
- abstract class Car
- private String name;
- public abstract void drive();
- public String getName()
- return name;
- public void setName(String name)
- this.name = name;
- //具体产品
- class Benz extends Car
- public void drive()
- System.out.println(this.getName()+"----go-----------------------");
- class Bmw extends Car
- public void drive()
- System.out.println(this.getName()+"----go-----------------------");
- //简单工厂
- class Driver
- public static Car createCar(String car)
- Car c = null;
- if("Benz".equalsIgnoreCase(car))
- c = new Benz();
- else if("Bmw".equalsIgnoreCase(car))
- c = new Bmw();
- return c;
- //老板
- public class BossSimplyFactory
- public static void main(String[] args) throws IOException
- //老板告诉司机我今天坐奔驰
- Car car = Driver.createCar("benz");
- car.setName("benz");
- //司机开着奔驰出发
- car.drive();
- <span style="font-family: courier new,courier;"></span>
如果老板要坐奥迪,同理。
这便是简单工厂模式了。那么它带了了什么好处呢?
首先,符合现实中的情况;而且客户端免除了直接创建产品对象的责任,而仅仅负责“消费”产品(正如暴发户所为)。
下面我们从开闭原则上来分析下简单工厂模式。当暴发户增加了一辆车的时候,只要符合抽象产品制定的合同,那么只要通知工厂类知道就可以被客户使用了。(即创建一个新的车类,继承抽象产品Car)那么 对于产品部分来说,它是符合开闭原则的——对扩展开放、对修改关闭;但是工厂类不太理想,因为每增加一辆车,都要在工厂类中增加相应的商业逻辑和判 断逻辑,这显自然是违背开闭原则的。
而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝类坏了。
正如我前面提到的简单工厂模式适用于业务简单的情况下或者具体产品很少增加的情况。而对于复杂的业务环境可能不太适应了。这就应该由工厂方法模式来出场了!!
四、工厂方法模式
抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
来用类图来清晰的表示下的它们之间的关系:
话说暴发户生意越做越大,自己的爱车也越来越多。这可苦了那位司机师傅了,什么车它都要记得,维护,都要经过他来使用!于是暴发户同情他说:我给你分配几个人手,你只管管好他们就行了!于是工厂方法模式的管理出现了。代码如下:
- //抽象产品
- abstract class Car
- private String name;
- public abstract void drive();
- public String getName()
- return name;
- public void setName(String name)
- this.name = name;
- //具体产品
- class Benz extends Car
- public void drive()
- System.out.println(this.getName()+"----go-----------------------");
- class Bmw extends Car
- public void drive()
- System.out.println(this.getName()+"----go-----------------------");
- //抽象工厂
- abstract class Driver
- public abstract Car createCar(String car) throws Exception;
- //具体工厂(每个具体工厂负责一个具体产品)
- class BenzDriver extends Driver
- public Car createCar(String car) throws Exception
- return new Benz();
- class BmwDriver extends Driver
- public Car createCar(String car) throws Exception
- return new Bmw();
- 深入理解JavaScript系列(29):设计模式之装饰者模式