设计模式
创建模式
定义:
创建型模式抽象了实例化过程。他们帮助一个系统独立于如何创建、组合和表示它的那些对象
一个类创建型模式使用继承改变被实例化的类,而一个对象创建模式是将实例化委托给另一个对象
类模式
Factory Method 工厂模式
意图
定一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类
动机:
主要解决接口选择的问题。
适用性
- 当一个类不知道它所必需创建的对象的类的时候
- 当一个类希望由它的字类来指定它所创建的对象的时候
- 当类将创建的职责委托给多个帮助字累中的某一个,并且你希望将哪一个字累帮助时代理者这一信息局部化的时候。
参与者
- product 定义工厂方法所创建的对象的接口
- ConcreteProduct 实现Product接口
- Creator 声明工厂方法,该方法返回一个Product 类型对象。Creator 也可以定义一个工厂方法的缺省实现,它返回一个缺省的ConcreteProduct对象
- ConcreteCreator 重定义工厂方法以返回一个ConcreteProduct对象
效果:
- 为字类提供挂钩:用工厂方法在一个类的内部创建对象通常比直接创建对象更灵活。Factory Method 给子类一个挂钩以提供对象的扩展版本。
- 链接平行的类层次
- 优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。
- 缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
结构
实现
product
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 offical PizzaStore box"); } public String getName() { return name; } }
ConcreteProduct
public class NYStyleCheesePizza extends Pizza { public NYStyleCheesePizza() { name = "NY Style Sauce and Cheese Pizza"; dough = "Thin Crust Dough"; sauce = "Marinara Sauce"; toppings.add("Grated Reggiano Cheese"); } } public class ChicagoStyleCheesePizza extends Pizza { public ChicagoStyleCheesePizza(){ name = "Chicago Style Deep Dish Cheese Pizza"; dough = "Extra Thick Crust Dought"; sauce = "Plum Tomato Sauce"; toppings.add("Shredded Mozzarella Cheese"); } void cut(){ System.out.println("Cutting the pizza into square slices"); } }
Creator
public abstract class PizzaStore { public Pizza orderPizza(String type){ Pizza pizza; pizza = createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } protected abstract Pizza createPizza(String type); }
ConcreteCreator
public class NYPizzaStore extends PizzaStore { @Override protected Pizza createPizza(String type) { if (type.equals("cheese")) { return new NYStyleCheesePizza(); } else if ("veggie".equals(type)) { return new NystyleVeggiePizza(): }else return null; } }
对象模式
Abstract Factory 抽象工厂
意图:
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
动机:
系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
客户仅与抽象类定义的接口交互,而不使用特定的具体类的接口
适用性
- 一个系统要独立于它的产品的创建,组合和表示时
- 一个系统要由多个产品系列中的一个来配置时
- 当你要强调一系列相关的产品对象的设计以便进行联合使用时
- 当你提供一个产品类库,而只想显示它们的接口而不是实现时
结构
参与者
- AbstractFactory(WidgetFacto)-声明一个创建抽象产品对象的操作接口
- ConcreteFactory(MotifWidgetFactroy,PMWidgetFactroy)-实现创建具体产品对象的操作
- AbstractProduct(Windows,ScrollBar)-为一类产品对象声明一个接口
- ConcreteProduct(ModifyWindow,MotifScrollBar)定义一个将被相应的具体工厂创建的产品对象,实现AbstractProduct 接口
- Client 仅使用由AbstractFactroy 和AbstractProduct 类声明的接口
效果
优点:
- 分离了具体的类
- 使得易于交换产品系列
- 有利于产品的一致性
缺点:
- 难以支持新种类的产品
结构
实现
AbstractProduct
public abstract class Pizza { String name; Dough dough; Sauce sauce; Veggies veggies[]; Cheese cheese; Pepperoni pepperoni; Clams clam; abstract void prepare(); 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("Please pizza in official PizzaStore box"); } void setName(String name) { this.name = name; } }
ConcreteProduct
public class ClamPizza extends Pizza { PizzaIngredientFactory ingredientFactory; public ClamPizza(PizzaIngredientFactory ingredientFactory) { this.ingredientFactory = ingredientFactory; } @Override void prepare() { System.out.println("Preparing" + name); dough = ingredientFactory.createDough(); sauce = ingredientFactory.createSauce(); cheese = ingredientFactory.createCheese(); clam = ingredientFactory.createClam(); } } public class CheesePizza extends Pizza { PizzaIngredientFactory ingredientFactory; @Override void prepare() { System.out.println("Preaparing " + name); dough = ingredientFactory.createDough(); sauce = ingredientFactory.createSauce(); cheese = ingredientFactory.createCheese(); } public CheesePizza(PizzaIngredientFactory ingredientFactory) { this.ingredientFactory = ingredientFactory; } }
AbstractFactory
public interface PizzaIngredientFactory { public Dough createDough(); public Sauce createSauce(); public Cheese createCheese(); public Veggies[] createVeggies(); public Pepperoni createPeppernoi(); public Clams createClam(); }
ConcreteFactory
public class NYPizzaIngredientFactory implements PizzaIngredientFactory { @Override public Dough createDough() { return new ThinCrustDough(); } @Override public Sauce createSauce() { return new MarinaraSauce(); } @Override public Cheese createCheese() { return new ReggianoChessse(); } @Override public Veggies[] createVeggies() { Veggies veggies[] = {new Garlic(),new Onion().new Mushroom(),new RedPepper()}; return veggies; } @Override public Pepperoni createPeppernoi() { return new SlicedPepperoni(); } @Override public Clams createClam() { return new FreshClams(); } }
Client
public class NYPizzaStore extends PizzaStore{ @Override protected 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"); } else if (type.equals("veggie")) { pizza = new VeggiePizza(ingredientFactory); pizza.setName("New York Style Veggie Pizza"); } return pizza; } }
Builder 构建者模式
意图
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
动机
将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
Builder模式将分析文本格式的算法与描述怎样创建和表示一个转换后格式的算法分离开。
适用性
- 当创建复杂对象的算法应独立于该对象的组成部分以及他们的装配方式时
- 当构造过程必须允许被构造的对象有不同的表示时
结构
参与者
- Builder为创建一个Product对象的各个部件指定抽象接口。
- ConcreteBuilder 实现builder接口以构造和装配该产品的各个部件,确定并明确它所创建的表示,提供一个检索产品的接口
- Director 构造一个使用Builder接口的对象
- Product 表示被构造的复杂对象。ConcreteBuilder创建该对象的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口
效果
- 它使你可以改变一个产品的内部表示
- 它将构造代码和表示代码分开
- 它使你可对构造过程进行更精细的控制
Prototype 原型模式
意图
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
动机
在运行期建立和删除原型。
Singleton 单例模式
意图
保证一个类仅有一个实例,并提供一个访问他的全局访问点
动机
保证一个类直邮一个实例并且易于被访问,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建(通过截取创建新对象的请求),并且它可以提供一个访问该实例的方法
适用性
- 当类职能有一个实例,且客户可以从一个众所周知的访问点访问它时
- 当这个唯一实例应该是通过子类可扩展的,并且用户无需更改代码就能使用一个扩展的实例时
参与者
哈哈哈,只有Singleton
- 定义一个Instance操作,允许客户访问它的唯一实例。Instance是一个类操作(即java中的 static方法)
- 可能负责创建他自己的唯一实例
协作:
- 客户只能通过SingleTone的Instance操作访问一个Singleton的实例
效果:
- 对唯一实例的受控访问
- 缩小名空间
- 允许对操作和表示的精化
- 允许可变数目的实例
- 比类操作更灵活
实现
真是尴尬的一个类
public class SingleObject {
//创建 SingleObject 的一个对象
private static SingleObject instance = new SingleObject();
//让构造函数为 private,这样该类就不会被实例化
private SingleObject(){}
//获取唯一可用的对象
public static SingleObject getInstance(){
return instance;
}
public void showMessage(){
System.out.println("Hello World!");
}
}
几种创建模式的区别
工厂模式和抽象工厂模式
不同:
工厂方法——类模式——通过继承
抽象工厂——对象模式——通过对象的组合
使用时间:
抽象工厂:当你需要创建产品家族和想让制造的相关产品集合起来时
工厂方法:可以把客户代码从需要实例化的具体类中解耦。或者如果目前还不知道将来需要实例化那些具体类时,也可以用工厂方法
相同:
两者都实现了将对象从具体类型中解耦,只不过实现方法不同
抽象工厂提供一个用来创建一个产品家族的抽象类型,这个类型的子类定义了产品被产生的方法,要想使用这个工厂,必须先实例化他,然后将它传入一些针对抽象类型所写的代码中。
工厂方法:核心——通过子类来创建对象。
总结:
用一个系统创建的那些对象的类对系统进行参数化油两种常用方法。
一种是生成创建对象的类的子类;这对于使用Factory Method模式。这种方法的主要缺点是,进为了改变产品类,就可能需要创建一个新的子类。这样的改变可能是级联的。
另一种对系统进行参数化的方法更多的依赖于对象符合:定义一个对象负责明确产品对象的类,并将它作为改系统的参数。这是Abstract Factory、Builder和prototype模式的关键特征。所有这三个模式都涉及到创建一个新的负责创建产品对象的“工厂对象”。Abstract Factory由这个工厂对象产生多个类的对象。Builder 由这个工厂对象使用一个相对复杂的协议,逐步创建一个复杂产品。Property由这个工厂对象通过拷贝原型对象来创建产品对象。
推荐
抽象工厂模式和工厂模式的区别? - 回答作者: caoglish http://zhihu.com/question/20367734/answer/82361745
真的很好