简单工厂(SimpleFactory)
简单工厂是类的一种创建模式, 又叫做静态工厂方法模式, 他由一个工厂对象决定创建出哪一种产品的实例。(确切的说,我们像工厂类传入参数来决定
创建哪一个产品类的实例)
UML图如下:
我们以一个登录验证来实现一下简单工厂:
public interface Login{
//登录验证
public boolean verify(String name, String password);
}
public class DomainLogin implements Login{
@Override
public boolean verify(String name, String password){
//业务逻辑
return true;
}
}
public class PasswordLogin implements Login {
@Override
public boolean verify(String name, String password) {
// TODO Auto-generated method stub
/**
* 业务逻辑
*/
return true;
}
}
<span style="color:#FF0000;">
工厂类LoginManager,根据调用者不同的要求,
创建出不同的登录对象并返回。而如果碰到不合法的要求,
会返回一个Runtime异常</span>。
public class LoginManager {
public static Login factory(String type){
if(type.equals("password")){
return new PasswordLogin();
}else if(type.equals("passcode")){
return new DomainLogin();
}else{
/**
* 这里抛出一个自定义异常会更恰当
*/
throw new RuntimeException("没有找到登录类型");
}
}
}
测试类:
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
String loginType = "password";
String name = "name";
String password = "password";
Login login = LoginManager.factory(loginType);
boolean bool = login.verify(name, password);
if (bool) {
/**
* 业务逻辑
*/
} else {
/**
* 业务逻辑
*/
}
}
}
简单工厂的优点:
根据客户端给的参数动态的决定要实例化哪一个类,用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的。有利于整个软件体系结构的优化。而且提供了一个责任的分割,当系统改动时。(比如说上面的登录)无需修改调用者。
简单工厂的缺点:
这个工厂类集中了所以的创建逻辑,当有复杂的多层次等级结构时,所有的业务逻辑都在这个工厂类中实现。什么时候它不能工作了,整个系统都会受到影响。而且,如果有多种产品那么就都会混淆在工厂类里面,违背了单一原则。当我新增加一个产品的时候必须修改工厂类,相应的工厂类就需要重新编译一遍。这也违反了开闭原则。
工厂方法(Factory Meathod):
工厂方法的用意是定义一个创建产品对象的工厂接口,将实际的创建工作推迟到子类中去.
工厂方法模式的核心是一个抽象工厂类, 而简单工厂模式把核心放在一个具体类上。 工厂方法模式可以允许很多具体工厂类从抽象工厂类中将创建行为继承下来,这样做的好处是可以允许系统在不修改具体工厂类的情况下引进新的产品。
我们知道在上面的简单工厂中,实例化一个产品类取决于工厂类, 修改一个产品也需要改动工厂类。等等等
它知道的有点太多了, 我们知道一人专权后果很严重~。 所以我们决定改进一下。
首先,核心的工厂类不在负责所有的产品的创建。 而且直接被迫将权利给下面的“大臣”,也就是他的子类
所以工厂类摇身一变变成了抽象工厂类, 他只负责命令, 而不再是亲力亲为。下面是工厂方法涉及的角色名称:
具体产品角色: 这个角色实现了抽象产品角色所声明的接口。
我们以一个系统来演示工厂方法:
此类图和代码来自于Java与模式。 在这里抽象工厂类FruitGardener是抽象工厂角色(皇帝),但是他并没有掌握
生杀大权, 这项权利被交给了它的子类(法庭,威武威武的那种),即AppleGardener StawberryGardener 和
GrapeGardener.
/*抽象工厂角色 FruitGardener*/
public interface FruitGadrener{
/*
工厂方法
*/
public Fruit factory();
}
/*具体工厂类 AppleGardener*/
public class AppleGardener
implements FruitGardener
{
public Fruit factory()
{
return new Apple();
}
}
/*StrawberryGardener类是一个具体工厂类*/
public class StrawberryGardener
implements FruitGardener
{
public Fruit factory(){
return new Apple();
}
}
//抽象产品角色Fruit源码
public interface Fruit
{
void grow();
void harvest();
void plant();
}
// 具体产品类,实现了Fruit接口
public class Apple implements Fruit{
private int treeAge;
public void grow()
{
System.out.println("Apple is growing");
}
public void harvest(){
System.out.println("Apple harvested");
}
public void plant(){
System.out.println("Apple planted");
}
public int getTreeAge(){
return treeAge;
}
public void setTreeAge(int treeAge){
this.treeAge=treeAge;
}
}
/*具体产品类 Strawberry 源码如下:*/
public class Strawberry implements Fruit
{
public void grow()
{
System.out.println("Strawberry is growing");
}
public void harvest(){
System.out.println("Strawberry harvested");
}
public void plant(){
System.out.println("Strawberry planted");
}
}
/*具体产品类 Grape*/
public class Grape implements Fruit
{
private boolean seedless;
public void grow()
{
System.out.println("Grapeis growing");
}
public void harvest(){
System.out.println("Grape harvested");
}
public void plant(){
System.out.println("Grape planted");
}
public boolean getseedless(){
return seedless;;
}
public setseedless(){
this.seedless=seedless;
}
}
抽象工厂:
大家都知道工厂方法他所针对的就是一个产品族,也就是工厂方法所提供的产品都是来自一个接口,或者一个抽象类。 而抽象工厂的产品可以来自多个接口或者多个抽象类。 抽象工厂的用意就是像客户端提供一个接口,使得客户端在不必指定产品的具体
类型的情况下,创建多个产品族中产品对象。
根据里氏代换的原则,任何可以接收父类的地方,都应该接收子类型.(反之不成立),那么只要类型与这些抽象
的产品角色相同,工厂类就可以负责创建由抽象产品的具体子类。 如下:
举个栗子╭(╯^╰)╮:
以一个农村系统为例:
我们有2个产品等级结构,分别为 水果Fruit, 和蔬菜Veggie.
类图如下:
蔬菜类图:
他的产品等级结构:
用一个工厂族封装创建过程:
UML图如下:
public interface Gardener{}
public class NorthernGardener implements Gardener{
/*
水果的工厂方法
*/
public Fruit createFruit(String name)
{ return new NorthernFruit(name);}
/*蔬菜工厂方法*/
public Veggie createVeggie(String name)
{return new NorthernVeggie(name);}
}
public class TropicalGardener implements Gardener{
/*水果的工厂方法*/
public Fruit createFruit(String name){
return new TropicalFruit(name);
}
/*蔬菜的工厂方法*/
.public Veggie createVeggie(String name)
{return new TropicalVeggie(name);}
}
public class Veggie implements Veggie
{
private String name;
public NortthernVeggie(String name){ }
public String getName(){return name;}
public void setName(String name){this.name=name;}
}
/*具体产品类TropicalVeggie*/
public class TropicalVeggie implements Veggie
{
private String name;
public TropicalVeggie(String name){this.name=name;}
public String getName(){return name;}
public void setName(String name){this.name=name;}
}
/*抽象产品角色*/
public interface Fruit{}
/*抽象产品角色NorthernFruit*/
public class NorthernFruit implements Fruit
{
private String name;
public NorthernFruit(String name){ }
public String getName(){return name;}
public void setName(String name){this.name=name;}
}
/*抽象产品角色TropicalFruit*/
public class TropicalFruit implements Fruit
{
private String name;
public TropicalFruit(String name){}
public String getName(){return name;}
public void setName(String name){this.name=name;}
}
在使用时,客户端只需要创建具体工厂的实例,然后调用工厂对象的方法,就可以得到所需要的产品对象。