设计模式学习笔记(十一:抽象工厂模式)
Posted 舞动的心
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式学习笔记(十一:抽象工厂模式)相关的知识,希望对你有一定的参考价值。
1.1概述
提供一个创建一系列或相互依赖对象的接口,而无须指定他们具体的类。这就是抽象工厂模式的定义。
设计某些系统时可能需要为用户提供一系列相关的对象,但系统不希望用户直接使用new运算符实例化这些对象,而是应当由系统来控制这些对象的创建,否则用户不仅要清楚地知道使用哪些类来创建这些对象,而且还必须要清楚对象之间是如何关联的,使得用户的代码和这些类形成紧耦合、缺乏弹性、不利于维护。
例如,军队要为士兵(用户)提供机关枪、手枪以及相应的子弹,但军队系统不希望由士兵提供来生产机关枪、手枪以及子弹,而是由相应的工厂专门负责配套生产,即有一个专门负责生产机关枪、手枪、子弹的工厂。具体关系如下图一所示:
图一:兵工厂与枪械、子弹关系示意图(PS:仅仅作为示意图,不要纠结哟)
当系统准备为用户提供一系列相关的对象,又不想让用户代码和创建这些对象的类形成耦合时,就可以使用抽象工厂方法模式来设计系统。抽象工厂模式的关键是在一个抽象类或接口中定义若干个抽象方法,这些抽象方法分别返回某个类的实例,该抽象类或接口让其子类或实现该接口的类重写这些抽象方法为用户提供一系列相关的对象。
1.2模式的结构
抽象工厂模式的结构中包括四种角色:
(1)抽象产品(Product):一个抽象类或接口,负责定义具体产品必须实现的方法;
(2)具体产品(ConcreteProduct):具体产品是一个类,如果Product是一个抽象类,那么具体产品就是实现Product的子类;如果Product是一个接口,那么具体产品就是实现Product接口的类;
(3)抽象工厂(AbstractFactory):一个接口或抽象类,负责定义若干个抽象方法;
(4)具体工厂(ConcreteFactory):如果抽象工厂是抽象类,具体工厂就是抽象工厂的子类;如果抽象工厂是一个接口,那么具体工厂就是实现抽象工厂接口的类。具体工厂重写抽象工厂中的抽象方法是该方法返回具体产品的实例。
抽象工厂模式的类图如下图二所示:
图二:抽象工厂模式结构类图
1.3抽象工厂模式的优点
(1)抽象工厂可以为用户创建一系列相关的对象,使用户和创建这些对象的类脱耦。
(2)使用抽象工厂模式可以方便为用户创建一系列对象。用户使用不同的具体工厂就能得到一组相关的对象,同时也能避免用户混用不用系列中对象。
(3)在抽象工厂模式中,可以随时增加“具体工厂”为用户提供一组相关的对象。
1.4适合使用抽象工厂模式的情景
(1)系统需要为用户提供多个对象,但不希望用户直接用new运算符实例化这些对象,即希望用户和创建对象脱耦。
(2)系统需要为用户提供一系列对象,但只需要知道这些对象有哪些方法可用,不需要用户知道这些对象的创建过程。
1.5抽象工厂模式的使用
以下通过一个简单的问题来描述抽象工厂模式中所涉及的各个角色。
建立一个系统,该系统可以为用户提供西服套装和牛仔套装,具体如下:
首先看一下本实例构建框架具体类和1.2模式的结构中类图的对应关系,如下图所示:
(1)抽象产品(Product)
抽象产品角色涉及两个类UpperClothes类和Trousers类,分别用来刻画衣服的上装和下装。UpperClothes类和Trousers类的代码如下:
UpperClothes.java
package com.liuzhen.eleven_abstractFactory; public interface UpperClothes { public abstract int getChestSize(); public abstract int getHeight(); public abstract String getName(); }
Trousers.java
package com.liuzhen.eleven_abstractFactory; public interface Trousers { public abstract int getWaistSize(); public abstract int getHeight(); public abstract String getName(); }
(2)具体产品(ConcreteProduct)
具体产品有四个类WesternUpperClothes、CowboyUpperClothes、WesternTrousers、CowboyTrousers,其中WesternUpperClothes和CowboyUpperClothes是UpperClothes类的子类,WesternTrousers和CowboyTrouser是Trousers类的子类。这四个具体类的代码如下:
WesternUpperClothes.java
package com.liuzhen.eleven_abstractFactory; public class WesternUpperClothes implements UpperClothes { private int chestSize; private int height; private String name; WesternUpperClothes(String name , int chestSize , int height){ this.name = name; this.chestSize = chestSize; this.height = height; } public int getChestSize() { // TODO Auto-generated method stub return chestSize; } public int getHeight() { // TODO Auto-generated method stub return height; } public String getName() { // TODO Auto-generated method stub return name; } }
CowboyUpperClothes.java
package com.liuzhen.eleven_abstractFactory; public class CowboyUpperClothes implements UpperClothes { private int chestSize; private int height; private String name; CowboyUpperClothes(String name , int chestSize , int height){ this.name = name; this.chestSize = chestSize; this.height = height; } public int getChestSize() { // TODO Auto-generated method stub return chestSize; } public int getHeight() { // TODO Auto-generated method stub return height; } public String getName() { // TODO Auto-generated method stub return name; } }
WesternTrousers.java
package com.liuzhen.eleven_abstractFactory; public class WesternTrousers implements Trousers { private int waistSize; private int height; private String name; WesternTrousers(String name , int waistSize , int height){ this.name = name; this.waistSize = waistSize; this.height = height; } public int getWaistSize() { // TODO Auto-generated method stub return waistSize; } public int getHeight() { // TODO Auto-generated method stub return height; } public String getName() { // TODO Auto-generated method stub return name; } }
CowboyTrousers.java
package com.liuzhen.eleven_abstractFactory; public class CowboyTrousers implements Trousers { private int waistSize; private int height; private String name; CowboyTrousers(String name , int waistSize , int height){ this.name = name; this.waistSize = waistSize; this.height = height; } public int getWaistSize() { // TODO Auto-generated method stub return waistSize; } public int getHeight() { // TODO Auto-generated method stub return height; } public String getName() { // TODO Auto-generated method stub return name; } }
(3)抽象工厂(AbstractFactory)
担当抽象工厂角色的类是ClothesFactory,代码如下:
package com.liuzhen.eleven_abstractFactory; public abstract class ClothesFactory { public abstract UpperClothes createUpperClothes(int chestSize , int height); public abstract Trousers createTrousers(int waistSize , int height); }
(4)具体工厂(ConcreteFactory)
有两个具体工厂,分别是BeijingClothesFactory类(负责制作西装套装)和ShanghaiClothesFactory类(负责制作牛仔套装),这两个类代码如下:
BeijingClothesFactory.java
package com.liuzhen.eleven_abstractFactory; public class BeijingClothesFactory extends ClothesFactory { @Override public UpperClothes createUpperClothes(int chestSize, int height) { // TODO Auto-generated method stub return new WesternUpperClothes("北京牌西服上衣",chestSize,height); } @Override public Trousers createTrousers(int waistSize, int height) { // TODO Auto-generated method stub return new WesternTrousers("北京牌西服裤子",waistSize,height); } }
ShanghaiClothesFactory.java
package com.liuzhen.eleven_abstractFactory; public class ShanghaiClothesFactory extends ClothesFactory { @Override public UpperClothes createUpperClothes(int chestSize, int height) { // TODO Auto-generated method stub return new CowboyUpperClothes("上海牌牛仔上衣",chestSize,height); } @Override public Trousers createTrousers(int waistSize, int height) { // TODO Auto-generated method stub return new CowboyTrousers("上海牌牛仔裤子",waistSize,height); } }
(5)模式的使用
首先看一下Shop类代码:
package com.liuzhen.eleven_abstractFactory; public class Shop { UpperClothes cloth; Trousers trouser; public void giveSuit(ClothesFactory factory , int chestSize , int waistSize , int height){ cloth = factory.createUpperClothes(chestSize, height); trouser = factory.createTrousers(waistSize, height); showMess(); } private void showMess(){ System.out.println("<套装信息>"); System.out.println(cloth.getName()+":"); System.out.println("胸围:"+cloth.getChestSize()); System.out.println("身高:"+cloth.getHeight()); System.out.println(trouser.getName()+":"); System.out.println("腰围:"+trouser.getWaistSize()); System.out.println("身高:"+trouser.getHeight()); } }
通过ElevenApplication类来具体实现上述相关类和接口,来实现抽象工厂模式的运用,其代码如下:
package com.liuzhen.eleven_abstractFactory; public class ElevenApplication { public static void main(String args[]){ Shop shop = new Shop(); ClothesFactory factory = new BeijingClothesFactory(); shop.giveSuit(factory, 110,82,170); factory = new ShanghaiClothesFactory(); shop.giveSuit(factory, 120, 88, 180); } }
运行结果:
<套装信息> 北京牌西服上衣: 胸围:110 身高:170 北京牌西服裤子: 腰围:82 身高:170 <套装信息> 上海牌牛仔上衣: 胸围:120 身高:180 上海牌牛仔裤子: 腰围:88 身高:180
参考资料:
1.Java设计模式/耿祥义,张跃平著.——北京:清华大学出版社,2009.5
以上是关于设计模式学习笔记(十一:抽象工厂模式)的主要内容,如果未能解决你的问题,请参考以下文章
java/android 设计模式学习笔记---抽象工厂模式