zoukankan      html  css  js  c++  java
  • Java 设计模式之抽象工厂模式(三)

    原文地址:Java 设计模式之抽象工厂模式(三)
    博客地址:http://www.extlight.com

    一、前言

    上篇文章 《Java 设计模式之工厂模式(二)》,介绍了简单工厂模式和工厂方法模式,本篇将继续介绍工厂模式中的最后一个模式--抽象工厂模式。

    二、简单介绍

    抽象工厂模式是所有形态的工厂模式中最为抽象的。抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型(不是指实现类)的情况下,能够创建多个产品族的产品对象。

    产品族可以通入下图理解:

    image

    在上图中,有多个发动机、轮胎和座椅,它们都可以看作是单独的产品,我们将发动机、轮胎和座椅组成一个产品族,用于区分其他的发动机、轮胎和座椅。

    每个产品族又可以划分成高端、中端和低端系列产品。

    三、实现方式

    我们现在通过代码实现不同产品族中每个产品的创建。我们以高端和低端产品族为例。

    发动机接口和实现类:

    public interface Engine {
    
    	void run();
    }
    
    class HighEndEngine implements Engine {
    
    	@Override
    	public void run() {
    		System.out.println("高端发动机,启动快");
    	}
    	
    }
    
    class LowEndEngine implements Engine {
    	@Override
    	public void run() {
    		System.out.println("低端发动机,启动慢");
    	}
    }
    

    轮胎接口和实现类:

    public interface Tyre {
    
    	void use();
    }
    
    class HighEndTyre implements Tyre {
    
    	@Override
    	public void use() {
    		System.out.println("高端轮胎,耐磨防滑");
    	}
    	
    }
    
    class LowEndTyre implements Tyre {
    
    	@Override
    	public void use() {
    		System.out.println("低端轮胎,磨损大,易打滑");
    	}
    	
    }
    

    座椅接口和实现类:

    public interface Seat {
    
    	void feel();
    }
    
    class HighEndSeat implements Seat {
    
    	@Override
    	public void feel() {
    		System.out.println("高端座椅,坐着舒适");
    	}
    	
    }
    
    class LowEndSeat implements Seat {
    
    	@Override
    	public void feel() {
    		System.out.println("低端座椅,坐旧难受");
    	}
    	
    }
    

    工厂模式的前提:创建的实例通常都具有共同的父类,此处使用接口作为“父类”。

    如果使用工厂方法模式,代码如下:

    public interface EngineFactory {
        Engine createEngine();
    }
    
    public interface TyreFactory {
        Tyre createTyre();
    }
    
    public interface SeatFactory{
        Seat createSeat();
    }
    ...
    

    发动机、轮胎、座椅 3 个产品需要创建 3 个抽象工厂与 6 个实现类(高端和低端)。

    客户端调用:

    public class Client {
    
    	public static void main(String[] args) {
    		EngineFactory ef = new HighEndEngineFactory();
    		Engine engine = ef.createEngine();
    
            TyreFactory tf = new HighEndTyreFactory();
            Tyre tyre = tf.createTyre();
            
            SeatFactory sf = new HighEndEngineSeatFactory();
            Seat seat = sf.createSeat();
    		
    	}
    }
    

    如果需要拼装一辆高端的轿车,客户端需要创建 3 个高端的工厂获取发动机、轮胎和座椅才能完成需求。这样客户端就与多个类进行耦合,违反了迪米特法则。

    假设,高端产品族新增一个安全锁的产品,我们又要新建相应的抽象工厂和子类工厂。项目结构的复杂度大大增加。

    如果使用抽象工厂模式,我们站在产品族内部结构的角度思考,抽象工厂中方法对应产品结构,而具体工厂对应产品族中的各个产品,那么需求实现起来就轻松许多了。

    工厂接口:

    public interface CarFactory {
    
    	Engine createEngine();
    	
    	Tyre createTyre();
    	
    	Seat createSeat();
    }
    

    工厂实现类:

    public class HighEndCarFactory implements CarFactory {
    
    	@Override
    	public Engine createEngine() {
    		return new HighEndEngine();
    	}
    
    	@Override
    	public Tyre createTyre() {
    		return new HighEndTyre();
    	}
    
    	@Override
    	public Seat createSeat() {
    		return new HighEndSeat();
    	}
    
    
    }
    
    public class LowEndCarFactory implements CarFactory {
    
    	@Override
    	public Engine createEngine() {
    		return new LowEndEngine();
    	}
    
    	@Override
    	public Tyre createTyre() {
    		return new LowEndTyre();
    	}
    
    	@Override
    	public Seat createSeat() {
    		return new LowEndSeat();
    	}
    
    }
    

    客户端调用:

    public class Client {
    
    	public static void main(String[] args) {
    		CarFactory cf = new HighEndCarFactory();
    		
    		Engine engine = cf.createEngine();
    		
            Tyre tyre = cf.createTyre();
            
            Seat seat = cf.createSeat();
    	}
    }
    

    这种实现方式对应上文的内容:客户端在不必指定产品的具体类型(发动机、轮胎、座椅)的情况下,能够创建多个产品族的产品对象。当产品族中新增几个产品,只需创建产品类以及在对应的工厂类中添加对应的方法即可。

    在使用设计模式时,很难遵循五大原则和一大法则。我们使用设计模式是为了让代码具有可复用性、可扩展性和灵活性。不能一味地守着这几个规定,从而限制自己对编程的想象和发挥。

  • 相关阅读:
    php多态
    ssl certificate problem: self signed certificate in certificate chain
    test plugin
    open specific port on ubuntu
    junit vs testng
    jersey rest service
    toast master
    use curl to test java webservice
    update folder access
    elk
  • 原文地址:https://www.cnblogs.com/moonlightL/p/7806471.html
Copyright © 2011-2022 走看看