引言:
设计模式是一套反复被使用,多数人知晓,经过分类编目和时间沉淀的,是软件高级开发人员在开发过程遇到的一般性问题的一种解决方案,这些解决方案是软件高级开发人员在开发的过程中长期的不断试验和错误总结出来的,遵守一些设计模式可以开发高效,简洁又易于后期维护和管理的系统。
java的设计模式共有23中,其中又被一系列分类出来,分为创建型模式,结构型模式,行为型模式
创建型模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。
结构型模式:把类或对象结合在一起形成一个更大的结构。
行为型模式:类和对象如何交互,及划分责任和算法。
一:介绍简单工厂:
简单工厂其实并不是一种设计模式,而是一种编程习惯,可以让实例从客户端脱出来,具有松耦合性
例:
介绍一个披萨的制作和过程
Pizza:披萨
PizzaStore:披萨店
PizzaFactory:披萨生产工厂
public Pizza orderPizza(String pizzaType){
//一般情况下 我们都是直接用new 实例化对象,
//但是这样做弊端很大,客户端和实例的耦合度太高,不利于后期的代码维护和修改
Pizza pizza ;
if(PizzaEnum.DURIANPIZZA.getPizzaType().equals(pizzaType)){
pizza = new DurianPizza();
}else if(PizzaEnum.RELISHPIZZA.getPizzaType().equals(pizzaType)){
pizza = new RelishPizza();
}
//看看简单工厂的用法:
//多一步,在构造器传入简单工厂对象,
private PizzaFactory pizzaFactory;
public PizzaStore(PizzaFactory pizzaFactory ) {
this.pizzaFactory = pizzaFactory;
// TODO Auto-generat stub
//pizzaFactory = new PizzaFactory();
}
pizza = pizzaFactory.createPizza(pizzaType);
}
//简单工厂类
public class PizzaFactory {
//简单工厂方法
public Pizza createPizza(String type){
if(PizzaEnum.DURIANPIZZA.getPizzaType().equals(pizzaType)){
pizza = new DurianPizza();
}else if(PizzaEnum.RELISHPIZZA.getPizzaType().equals(pizzaType)){
pizza = new RelishPizza();
}else{
return new Pizza();
}
}
}
主要是在orderPizza中做了Pizza实例的变换过程,转由pizzaFactory工厂来制作,好处就是将实例与客户端代码分离,减少耦合度。
二:介绍工厂模式:
由于披萨店(pizzaStore)的知名度越来越高,现总部需要开设东部和西部俩间披萨店,
现在的问题是因地域问题,俩间披萨店的人群口味大小不一致,导致现在的代码需大幅度改动(PizzaStore类),
如果我们一开始就打算设计一种思路将披萨的制作由每个分店独立进行,这样是否可行呢?
开始我们的思路吧:
1,将pizzaStore重构: 旧代码是 orderPizza调用pizza工厂产生披萨,现在我们的目标是由各分店自行制作
//工厂方法,交由具体子类分店实现
protected abstract Pizza createPizza(String pizzaType);
在pizzaStore加上一个 pizza生产的抽象类
orderPizzaf(String pizzaType)改为:
pizza = createPizza(pizzaType);
现在的变化是本来由pizzaStore负责生产披萨的转由子类实现来生产披萨,这样就符合了我们制作不同口味的目标了。
来看看俩间店的风格吧:
//西部分店
public class WestPizzaStore extends PizzaStore{
//子类自己实现工厂方法
@Override
protected Pizza createPizza(String pizzaType) {
if(PizzaEnum.DURIANPIZZA.getPizzaType()==pizzaType){
return new WestDurianpizza();
}else if(PizzaEnum.RELISHPIZZA.getPizzaType()==pizzaType){
return new WestRelishPizza();
}else {
return new Pizza();
}
}
}
/**
* 东部分店
* @author Administrator
*
*/
public class EastPizzaStore extends PizzaStore{
@Override
protected Pizza createPizza(String pizzaType) {
if(PizzaEnum.DURIANPIZZA.getPizzaType()==pizzaType){
return new EastDurianPizza();
}else if(PizzaEnum.RELISHPIZZA.getPizzaType()==pizzaType){
return new EastRelishPizza();
}else {
return new Pizza() {
};
}
现在的披萨制作完全是由子类来承担,这其实就是大名鼎鼎的工厂方法模式:
工厂模式定义:定义了一个创建对象的接口,但由子类来决定实例化的类是哪个,工厂方法模式把对象的创建延迟到子类。
三:介绍抽象工厂模式:
紧接着由于店面的扩大,Pizza的原料制作也似乎也得进行改进,为了更符合东部西部俩地的披萨口味,我们打算开始建设一个原料工厂,将俩地各种需要原料输送过去
/**
* pizza原料工厂
* @author Administrator
*/
public interface PizzaMaterialFactory {
//芝士
public Ginger getGinger();
//奶酪
public Garlic getGarlic();
}
/**
* 东部原料接收工厂
* @author Administrator
*/
public class EastPizzaMaterial implements PizzaMaterialFactory{
@Override
public Ginger getGinger() {
//东部的芝士
return new EastGinger();
}
@Override
public Garlic getGarlic() {
//东部的奶酪
return new EastGarlic();
}
}
/**
* 西部原料接收工厂
* @author Administrator
*/
public class WestMeterial implements PizzaMaterialFactory{
@Override
public Ginger getGinger() {
//西部芝士
return new WestGinger();
}
@Override
public Garlic getGarlic() {
//西部奶酪
return new WestGarlic();
}
}
在各自的pizzaStore构造引入原料工厂
private PizzaMaterialFactory pizzaMaterialFactory ;
public WestPizzaStore(PizzaMaterialFactory pizzaMaterialFactory) {
// TODO Auto-generated constructor stub
this.pizzaMaterialFactory=pizzaMaterialFactory;
}
private PizzaMaterialFactory pizzaMaterialFactory;
public EastPizzaStore(PizzaMaterialFactory pizzaMaterialFactory ) {
this.pizzaMaterialFactory= pizzaMaterialFactory;
}
main方法测试:
//原料工厂
//西部原料
PizzaMaterialFactory pizzaMaterialFactory = new WestMeterial();
//东部原料
PizzaMaterialFactory pizzaMaterialFactory1 = new EastPizzaMaterial();
//西部披萨分店
PizzaStore pizzaStore = new EastPizzaStore(pizzaMaterialFactory1);
//东部披萨分店
PizzaStore pizzaStore2 = new WestPizzaStore(pizzaMaterialFactory);
来看看我们的成果吧:
通过引入原料工厂,我们定义了一系列的产品家族(奶酪,芝士...),利用抽象工厂接口,我们的代码将从客户端解耦,应用于不同的上下文环境制造不同的具体工厂,这些产品具有相同的接口却有着不同的实现,达到符合不同地区所需的原料。
抽象工厂模式:提供一个接口,用于创建相关或依赖对象的产品家族而不需要明确定义具体类
现在请俩种模式来采访一下吧:
俩种模式都是采用不同的方式创建对象的:
工厂方法:我采用的是继承,通过子类的实现来创建我的对象
抽象工厂:我采用的是对象的组合来创建一组对象。
整个工厂方法模式就是通过子类来创建对象,达到延迟创建,和客户端解耦。
抽象工厂就是工厂方法的一个大抽象集合吧,可以创建一组对象,也达到和客户端的解耦。
抽象工厂的一个缺点:如果要添加一个新的产品到产品家族,意味着所有的子类都得添加一个接口,这个改动是很大的。
结尾总结:
(以上例子均参考Head First设计模式书籍)
不管是简单工厂,工厂方法,抽象工厂都是为了创建对象实例,达到避免和客户端的高耦合,通过不同的手段降低偶尔性,隔离实例和客户端。
这边也用到一个原则:依赖倒置原则, 依赖倒置原则要求我们尽量依赖于接口而不是具体类,有益于后期的改动和维护。