3.具体产品角色
具体产品实现类一定是抽象产品类的实现或扩展。为了保证工厂类能够创建对象,工厂类需要知道具体产品的创建方式,这就涉及到具体产品类所提供的构造方法,以便,可能工厂类会向客户端提供具体创建服务所需要的数据。例如:某个产品类需要通过一个账号才能构造其实例,所以工厂类必须根据它的创建需求,为客户端提供一个带账号参数的生产方法,才能创建该具体产品类的对象。
也就是说,工厂类依赖于具体产品实现类。同样,客户端类是依赖于工厂类的。
通过上述三个角色的描述,我们应该能够了解,系统中哪些类能够胜任上述的三个角色,并通过各类之间的关系,通过工厂模式来实现系统或者某个模块。在实际的设计过程中,可能不存在完全与上述基本简单工厂模式完全适应的,需要根据具体的需求来调整简单工厂模式的应用。只要能够实现系统的良好设计,有时候变化才能满足需要。
下面用一个简单的例子来说明一下,给大家加深一下印象(例子来自于网络):
运动员.java public interface 运动员 { public void 跑(); public void 跳(); } 足球运动员.java public class 足球运动员 implements 运动员 { public void 跑(){ //跑啊跑 } public void 跳(){ //跳啊跳 } } 篮球运动员.java public class 篮球运动员 implements 运动员 { public void 跑(){ //do nothing } public void 跳(){ //do nothing } } 体育协会.java public class 体育协会 { public static 运动员 注册足球运动员(){ return new 足球运动员(); } public static 运动员 注册篮球运动员(){ return new 篮球运动员(); } } 俱乐部.java public class 俱乐部 { private 运动员 守门员; private 运动员 后卫; private 运动员 前锋; public void test() { this.前锋 = 体育协会.注册足球运动员(); this.后卫 = 体育协会.注册足球运动员(); this.守门员 = 体育协会.注册足球运动员(); 守门员.跑(); 后卫.跳(); } }
以上就是简单工厂模式的一个简单实例,读者应该想象不用接口不用工厂而把具体类暴露给客户端的那种混乱情形吧(就好像没了体育总局,各个俱乐部在市场上自己胡乱的寻找仔细需要的运动员),简单工厂就解决了这种混乱。
工厂方法模式
工厂方法模式是类的创建模式,又叫虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymorphic Factory)模式。 工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际工作推迟到子类中。
工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。工厂方法模式的对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不在负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。
工厂方法模式角色与结构
1.抽象工厂(Creator)角色:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
2.具体工厂(Concrete Creator)角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
3.抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
4.具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
工厂方法模式的一般结构,如图所示:
我们在不改变产品类(“足球运动员”类和“篮球运动员”类)的情况下,写一下工厂方法模式的例子:
运动员.java public interface 运动员 { public void 跑(); public void 跳(); } 足球运动员.java public class 足球运动员 implements 运动员 { public void 跑(){ //跑啊跑 } public void 跳(){ //跳啊跳 } } 篮球运动员.java public class 篮球运动员 implements 运动员 { public void 跑(){ //do nothing } public void 跳(){ //do nothing } } 体育协会.java public interface 体育协会 { public 运动员 注册(); } 足球协会.java public class 足球协会 implements 体育协会 { public 运动员 注册(){ return new 足球运动员(); } } 篮球协会.java public class 篮球协会 implements 体育协会 { public 运动员 注册(){ return new 篮球运动员(); } } 俱乐部.java public class 俱乐部 { private 运动员 守门员; private 运动员 后卫; private 运动员 前锋; public void test() { 体育协会 中国足协 = new 足球协会(); this.前锋 = 中国足协.注册(); this.后卫 = 中国足协.注册(); 守门员.跑(); 后卫.跳(); } }
很明显可以看到,“体育协会”工厂类变成了“体育协会”接口,而实现此接口的分别是“足球协会”“篮球协会”等等具体的工厂类。
这样做有什么好处呢?很明显,这样做就完全OCP了。如果需要再加入(或扩展)产品类(比如加多个“乒乓球运动员”)的话就不再需要修改工厂类了,而只需相应的再添加一个实现了工厂接口(“体育协会”接口)的具体工厂类。
抽象工厂模式
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据LSP原则,任何接受父类型的地方,都应当能够接受子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例。
先来认识下什么是产品族: 位于不同产品等级结构中,功能相关联的产品组成的家族。还是让我们用一个例子来形象地说明一下吧。
抽象工厂模式中的有以下的四种角色:
抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。
具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。
抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
具体产品(Concrete Product)角色:这个角色用以代表具体的产品。
Abstract Factory模式的结构:
package abstractFactory; public interface KitchenFactory{ public Food getFood(); public TableWare getTableWare(); } 抽象餐具的接口定义如下所示: package abstractFactory; public interface TableWare{ public String getTool(); } 抽象事物的接口定义如下所示: package abstractFactory; public interface Food{ public String getEatable(); } 而具体的实现也非常简单,以AKitchen为例子 具体工厂AKitchen的定义如下所示; package abstractFactory; public class AKitchenimplements KitchenFactory{ public Food getFood(){ return new Milk(); } public TableWare getTableWare(){ return new Spoon(); } } 具体餐具(spoon)的定义如下所示: package abstractFactory; public class Spoonimplements TableWare{ public String getTool() { return "spoon"; } } 具体食物(milk)的定义如下所示: package abstractFactory; public class Milkimplements Food{ public String getEatable(){ return "milk"; } } 客户端的定义如下: package abstractFactory; public class Client{ public void eat(KitchenFactory k){ System.out.println("A person eat "+k.getFood().getEatable() +" with "+k.getTableWare().getTool()+"!"); } public static void main(String[] args){ Client client=new Client(); KitchenFactory kf =new AKitchen(); client.eat(kf); kf=new BKitchen(); client.eat(kf); kf=new CKitchen(); client.eat(kf); } }
在以下情况下应当考虑使用抽象工厂模式:
· 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
· 这个系统有多于一个的产品族,而系统只消费其中某一产品族。
· 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
· 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
————————————————
版权声明:本文为CSDN博主「chen.yu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011068702/article/details/49342027