创建型模式之工厂模式
工厂模式
1. 简单工厂模式
2. 工厂方法
3. 抽象工厂模式
1.简单工厂模式(Simple Factory pattern):
属于类的创新型模式,又叫静态工厂方法模式(Static Factory Method Pattern);是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
① 工厂角色(SimpleFactory):
这是简单工厂模式的核心,由它负责创建所有的类的内部逻辑,当然工厂类必须能够被外界调用,创建所需要的产品对象。
② 抽象(IProduct)产品角色:
简单工厂模式所创建的所有对象的父类,注意,这里的父类可以是接口也可以是抽象类,它负责描述所有实例所共有的公共接口。
③具体产品(Concrete Product)角色:
简单工厂所创建的具体实例对象,这些具体的产品往往拥有共同的父类。
简单工厂模式优点:
直接创建所需实例,无需了解对象是如何创造以及如何组织的,有利于整个软件体系的优化。
简单工厂模式缺点:
工厂类集中了所有实例的创建逻辑,一旦该工厂出现问题,所有客户端都将受到牵连。更重要的是违背了“开放封闭原则”。
简单工厂模式实例:
抽象产品角色:
package com.szxy.LemonSnm;
public interface IFood {
void eat(); //抽象产品 可以吃
}
具体产品角色1(薯条)
package com.szxy.LemonSnm;
/*
薯条
*/
public class Chips implements IFood{
@Override
public void eat() {
System.out.println("我们吃到了薯条");
}
}
具体产品角色2(麦香鸡)
package com.szxy.LemonSnm;
/*
麦香鸡
*/
public class McChickn implements IFood {
@Override
public void eat() {
System.out.println("我们吃到了麦香鸡");
}
}
工厂角色(麦当劳商店)
package com.szxy.LemonSnm;
/*
麦当劳
*/
public class McDonlad {
public IFood getFood(String name){
switch(name){
case "chip":
return new Chips();
case "mcChicken":
return new McChickn();
default:
System.out.println("不能提供此产品");
return null;
}
}
}
客户端测试
package com.szxy.LemonSnm;
public class Client {
public static void main(String[] args) {
System.out.println("this is Simple Factory main");
McDonlad mcDonlad = new McDonlad(); //创建消费者
IFood food = mcDonlad.getFood("chip");//购买薯条
if (food !=null){
food.eat();
}
food = mcDonlad.getFood("mcChicken");//购买麦香鸡
if (food !=null){
food.eat();
}
food = mcDonlad.getFood("flsChicken");//购买符离集烧鸡
if (food !=null){
food.eat();
}
}
}
2、工厂方法:
一个抽象产品派生出多个具体产品类;一个抽象工厂类派生出多个具体工厂类;每个具体工厂类只能创建一个具体产品类的实例。
既定义一个创建对象的接口(即抽象工厂类),让其子类(具体工厂类)决定实例化哪一个类(具体产品类),“一对一”的关系。
① 工厂接口:
工厂接口是工厂方法模式的核心,与调用者直接交互用来提供产品。在实际编程中,有时候也会使用一个抽象类来与调用者交互的接口,其本质上是一样的。
②工厂实现:
在编程中,工厂实现决定如何实例化产品,是实现扩展的途径,需要有多少种产品,就需要多少个具体的工厂实现。
③产品接口:
主要目的是定义产品的规范,所有产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。同样,产品接口也可以用抽象类来代替,但要注意最好不要违反里氏替换原则。
④产品实现:
实现产品接口的具体类,决定了产品在客户端的具体行为。
工厂方法优点:
①在工厂方法中,用户只需要知道所有产品的具体工厂,无须关心具体的创建过程,甚至不需要具体产品类的类名。
②在系统中增加新产品时,只需要添加一个具体产品类和对应的实现工厂,无需对原工厂进行任何修改,很好地符合了“开闭原则”。
工厂方法缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,那么系统类中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
工厂方法与简单工厂对比:
工厂方法模式是简单工厂模式的延伸。在工厂方法模式中,核心工厂类不在负责产品的创建,而是将具体的创建工作交给子类去完成。也就是核心工厂仅仅只是提供创建的接口,具体实现方法交给继承它的子类去完成。
当我们的系统需要增加其他新的对象时,我们只需要添加一个具体的产品和它的创建工厂即可,不需要对原工厂进行任何修改,这样很好地符合了“开闭原则”。
工厂方法实例:
工厂接口(抽象商店):
package com.szxy.LemonSnm;
public interface Store {
IChips setFood();//生产食物
}
工厂1实现(必胜客商店):
package com.szxy.LemonSnm;
public class BscStore implements Store {
@Override
public IChips setFood() {
System.out.println("生产了必胜客薯条");
return new BscoChips();
}
}
工厂2实现(肯德基商店):
package com.szxy.LemonSnm;
public class CosChips implements IChips{
@Override
public void eat() {
System.out.println("吃到了肯德基的薯条");
}
}
工厂3实现(麦当劳商店):
package com.szxy.LemonSnm;
public class McStore implements Store {
@Override
public IChips setFood() {
System.out.println("产生了麦当劳薯条");
return new McChips();
}
}
产品接口(抽象产品薯条):
package com.szxy.LemonSnm;
public interface IChips {
public void eat();//吃到薯条
}
产品1实现(必胜客薯条):
package com.szxy.LemonSnm;
public class BscoChips implements IChips {
@Override
public void eat() {
System.out.println("吃到了必胜客的薯条");
}
}
产品2实现(肯德基薯条):
package com.szxy.LemonSnm;
public class CosChips implements IChips{
@Override
public void eat() {
System.out.println("吃到了肯德基的薯条");
}
}
产品3实现(麦当劳薯条):
package com.szxy.LemonSnm;
public class McChips implements IChips{
@Override
public void eat() {
System.out.println("吃到了麦当劳的薯条");
}
}
客户端测试
package com.szxy.LemonSnm;
public class Client {
public static void main(String[] args) {
System.out.println("this is Factory Method main");
Store store = new CosStore(); //肯德基商店
store.setFood().eat();
store = new McStore(); //麦当劳商店
store.setFood().eat();
store = new BscStore(); //必胜客商店
store.setFood().eat();
}
}
3、抽象工厂:
多个抽象产品类,派生出多个具体产品类;一个抽象工厂类,派生出多个具体工厂类;每个具体工厂类可以创建多个具体产品类的实例。
既提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们的具体的类。“一对多”的关系。
三者比较:
他们都属于工厂模式,在形式和特点上也是极为相似的,最总目的都是为了解耦。
在使用中,不必在意这个模式是工厂方法模式还是抽象工厂模式,他们之间可以互相转换。所以,在使用工厂模式时,只需要关心是否降低了耦合度。
工厂接口(抽象商店):
package com.szxy.LemonSnm;
public interface Store {
IChips setFood();//生产食物
Coke setCoke(); //生产可乐
}
工厂1实现(肯德基商店):
package com.szxy.LemonSnm;
public class CosChips implements IChips{
@Override
public void eat() {
System.out.println("吃到了肯德基的薯条");
}
}
产品1实现(肯德基薯条):
package com.szxy.LemonSnm;
public class CosChips implements IChips{
@Override
public void eat() {
System.out.println("吃到了肯德基的薯条");
}
}
产品2实现(肯德基可乐):
package com.szxy.LemonSnm;
public class CosCoke implements Coke {
@Override
public void eat() {
System.out.println("我们喝到了肯德基的可乐");
}
}
客户端测试:
package com.szxy.LemonSnm;
public class Client {
public static void main(String[] args) {
System.out.println("this is Abstract Factory main");
//想喝肯德基可乐
Store store = new CosStore(); //有个肯德基商店
Coke coke = store.setCoke(); //生产可乐
coke.eat(); //喝可乐
//想吃肯德基薯条
store = new CosStore(); //有个肯德基商店
IChips iChips = store.setFood(); //生产薯条
iChips.eat(); //吃薯条
}
}