1,简单的工厂模式
简单的说就是通过一个工厂类,对接口和类进行统一的管理。
我们先通过一个例题来说明一问题。
例子:我要买手机。
1,定义接口,用来买手机。
public interface OnPhone { /** * 要购买的手机. */ void payPhone(); }
2,创建各种品牌的手机,实现上面的接口。
//小米 public class Mi implements OnPhone { @Override public void payPhone() { System.out.println("我是小米,万物基于MIUI,便宜又实惠,买了"); } } //华为 public class Huawei implements OnPhone { @Override public void payPhone() { System.out.println("有点贵哈,但是没有啥大问题,买了"); } } //苹果 public class Pingguo implements OnPhone { @Override public void payPhone() { System.out.println("这个更贵,不过有钱,任性,买了"); } }
接着就是我们的测试类
//买了两部手机 public class Text { public static void main(String[] args) { OnPhone mi = new Mi(); mi.payPhone(); OnPhone pingguo = new Pingguo(); pingguo.payPhone(); } }
结果如下,
我是小米,万物基于MIUI,便宜又实惠,买了
这个更贵,不过有钱,任性,买了
我们观察上面的代码,其实是很好的完成了任务,但是我们的实现类和接口紧密的连接在了一起,耦合很高,在想一下,你要买手机,直接去找厂家买吗?,肯定是找一个代理人,或者是一个官方的软件呀,所以就引出了工厂模式。
我门在添加一个类Fragory,用它来管理手机,你要买什么只要找它就行。
public class Fragory { public static final int TYPE_MI = 1;//小米 public static final int TYPE_HUA= 2;//华为 public static final int TYPE_pingguo = 3;//苹果 public static OnPhone createPhone(int type){ switch(type){ case TYPE_MI: return new Mi(); case TYPE_HUA: return new Huawei(); case TYPE_pingguo: return new Pingguo(); default: System.out.println("没有这种手机"); return null; } } }
只要调用这个类的静态工厂的方法里传入你需要购买的手机,然后就好了。如下所示:
public class Text { public static void main(String[] args) { OnPhone phone = Fragory.createPhone(Fragory.TYPE_MI); phone.payPhone(); } }
下面我们看一下这个模式的优点和缺点:
优点:
通过一个静态的方法。就可以拿到所需要的东西,降低了耦合度。
简单的工厂模式包含必要的判断逻辑,简单工厂实现了对象的创建和使用的分离。
在不修改任何客户端代码的情况下更换和怎家新的具体产品类,在一定程度上提高了系统的灵活性。
缺点:
扩展性很差,如果有很多部手机的话,就好定义很多的类,每一个类对应着一部手机。而且还要修改静态工厂,这样就违反了封闭原则,而且会变得非常麻烦。
工厂类的职责过重,如果静态工厂出现了问题,则整个系统都会出现问题。
简单工厂的静态方法,使得工厂角色无法形成基于继承的等级结构。
工厂方法:
工厂方法则避免了 违反开放封闭原则,其实他的实现方法也非常简单,就是每个产品都对应着一个工厂。
如上面简单工厂,简单的说就是多个产品对应着一个静态的工厂方法。而工厂方法则是多个产品对应着多个工厂。下面我们看一下实现;
1,定义产品抽象类:
//产品抽象类 public abstract class Product { //显示产品 public abstract void show(); }
2,定义产品实现类:
public class ProductMi extends Product{ public void show() { System.out.println("生产小米手机"); } } public class ProdcutHuaWei extends Product{ public void show() { System.out.println("生产华为手机"); } } public class ProductPingGuo extends Product{ public void show() { System.out.println("生产苹果手机"); } }
3,定义工厂抽象类。
public abstract class Fractory { String name; //工厂名字 public Fractory(String name){ this.name = name; print(); } public void print(){ System.out.println(name); } //生产东西 public abstract Product setProduct(); }
4,定义工厂的实现类,每个产品对应一个工厂实现类。
public class FractoryMi extends Fractory { public FractoryMi() { super("我是小米工厂"); } @Override public Product setProduct() { // TODO Auto-generated method stub return new ProductMi(); } } public class FractoryHuaWei extends Fractory{ public FractoryHuaWei() { super("我是华为工厂"); } @Override public Product setProduct() { return new ProdcutHuaWei(); } } public class FractoryPingguo extends Fractory{ public FractoryPingguo() { super("我是苹果工厂"); } @Override public Product setProduct() { return new ProductPingGuo(); } }
每个工厂里面都有自己的名字,并且创建一个对应的产品对象,通过向上转型返回了出去。
5,使用:
public class Go { public static void main(String[] args) { FractoryMi mi = new FractoryMi(); mi.setProduct().show(); } }
结果如下:
我是小米工厂
生产小米手机
通过创建对应的产品工厂,就可以拿到对应的产品对象,然后调用他的shou方法。
优点:
通过常见对应的产品工厂,就能拿到对应的产品对象,同时隐藏了产品被实例化的细节。用户只需要关注工厂,就可以了,不需要知道产品实现的细节。
在创建新产品的时候,只需要增加工厂和创建的产品分别实现对应的抽象类就好了,完全符合 封闭性原则。
创建对象的细节完全封装在具体的工厂内部,而且有了抽象的工厂类,所有的工厂都继承了自己的父类!完美的体现了多态。
缺点;
在增加新的产品时,也必须增加细心地工厂类,会造成额外的开销。
抽象层的加入使得理解起来变得有点困难。