最近看工厂方法模式时有点疑问,请各位帮忙解决一下~
如下:
我在教程上看到说,如果想在系统中新加一个新的产品,则只需要向系统中加入一个新的产品类,以及他所对就原工厂类即可.而不用修改客户端代码.
我觉得客户端代码还是要需改的,请问这是为什么啊?哪儿理解有问题啊~!
在线等~1

解决方案 »

  1.   

    此回复为自动发出,仅用于显示而已,并无任何其他特殊作用
    楼主【feiyuxianwan】截止到2008-07-25 11:20:13的历史汇总数据(不包括此帖):
    发帖的总数量:27                       发帖的总分数:420                      每贴平均分数:15                       
    回帖的总数量:15                       得分贴总数量:3                        回帖的得分率:20%                      
    结贴的总数量:6                        结贴的总分数:100                      
    无满意结贴数:0                        无满意结贴分:0                        
    未结的帖子数:21                       未结的总分数:320                      
    结贴的百分比:22.22 %               结分的百分比:23.81 %                  
    无满意结贴率:0.00  %               无满意结分率:0.00  %                  
    楼主该结一些帖子了
      

  2.   

    首先应该是有需求,才会增加新的产品客户端的代码原来的代码是不用改动的。getInstance("A")这样是没有影响的,原来的产品还是继续生产。
      

  3.   

    这个要有个实例框架才好跟你解释. 一般来说如果新加一个产品,就得写一个新的class实现与其它产品相同的一个接口,调用者那边就不必关心你的新的class内部的逻辑如何写,我只需要调用接口中的函数就可以了. 
    我觉得我们平时经常使用的数据库例子就是很好的工厂模式的例子, 各种数据库jdbc中的class都实现了java.util.sql 下的接口, 
    我们"客户端"调用的语句 
    ResultSet rs = stmt.executeQuery("select * from table1");  
    就是说如何有一天,你自己增加一种数据库,只要实现java.util.sql 下的 接口, 
    客户端同样用:ResultSet rs = stmt.executeQuery("select * from table1");  就可以得到结果. 这应该就是说你所说的客户端不用修改代码的情况了.
      

  4.   

    java.util.sql 包 应该是 java.sql 包
      

  5.   

    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:Fruit.java
     * User:    LavaSoft
     * Date:    2006-12-3
     * Time:    17:25:48
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  水果接口
     */
    public interface Fruit {
        /**
         * 种植
         */
        void plant();
        /**
         * 生长
         */
        void grow();
        /**
         * 收获
         */
        void harvest();
    }
     
    1.2.3.3.2 具体产品苹果Apple.java
    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:Apple.java
     * User:    LavaSoft
     * Date:    2006-12-1
     * Time:    0:47:25
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  水果工厂的产品:苹果
     */
    public class Apple implements Fruit {
        private int treeAge;
        /**
         * 种植
         */
        public void plant() {
            System.out.println("Apple has been planted.");
        }
        /**
         * 生长
         */
        public void grow() {
            System.out.println("Apple is growing...");
        }
        /**
         * 收获
         */
        public void harvest() {
            System.out.println("Apple has been harvested.");
        }
        /**
         * @return 返回树龄
         */
        public int getTreeAge() {
            return treeAge;
        }
        /**
         * 设置树龄
         */
        public void setTreeAge(int treeAge) {
            this.treeAge = treeAge;
        }
    }1.2.3.3.3 具体产品葡萄:Grape.java
    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:Grape.java
     * User:    LavaSoft
     * Date:    2006-12-1
     * Time:    0:36:56
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  水果工厂的产品:葡萄
     */
    public class Grape implements Fruit {
        private boolean seedless;   //是否有籽
        /**
         * 种植
         */
        public void plant() {
            System.out.println("Grape has been planted.");
        }
        /**
         * 生长
         */
        public void grow() {
            System.out.println("Grape is growing...");
        }
        /**
         * 收获
         */
        public void harvest() {
            System.out.println("Grape has been harvested.");
        }
        /**
         * @return 是否有籽
         */
        public boolean getSeedless() {
            return seedless;
        }
        /**
         * 有无籽的赋值方法
         */
        public void setSeedless(boolean seedless) {
            this.seedless = seedless;
        }
        /**
         * 辅助方法
         */
        public static void log(String msg) {
            System.out.println(msg);
        }
    }1.2.3.3.4 具体产品草莓:Strawberry.java
    package com.lavasoft.patterns.factorymethod.ybms;/**
     * Created by IntelliJ IDEA.
     * FileName:Strawberry.java
     * User:    LavaSoft
     * Date:    2006-12-1
     * Time:    0:45:09
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  水果工厂的产品:草莓
     */
    public class Strawberry implements Fruit {
        /**
         * 生长
         */
        public void grow() {
            System.out.println("Strawberry is growing...");
        }
        /**
         * 收获
         */
        public void harvest() {
            System.out.println("Strawberry has been harvested.");
        }
        /**
         * 种植
         */
        public void plant() {
            System.out.println("Strawberry has been planted.");
        }
        /**
         * 辅助方法
         */
        public static void log(String msg) {
            System.out.println(msg);
        }
    }
     
    1.2.3.3.5 水果工厂接口:FruitGardener.java
    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:FruitGardener.java
     * User:    LavaSoft
     * Date:    2006-12-3
     * Time:    17:22:52
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  水果工厂接口
     */
    public interface FruitGardener {
        /**
         * 工厂方法
         *
         * @return 水果
         */
        public Fruit factory();
    }
     
    1.2.3.3.6 苹果工厂:AppleGardener.java
    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:AppleGardener.java
     * User:    LavaSoft
     * Date:    2006-12-3
     * Time:    17:45:29
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  苹果工厂方法
     */
    public class AppleGardener implements FruitGardener {
        /**
         * 工厂方法
         *
         * @return 苹果
         */
        public Fruit factory() {
            Fruit f = new Apple();
            System.out.println("水果工厂(AppletGardener)成功创建一个水果:苹果!");
            return f;
        }
    }
     
    1.2.3.3.7 葡萄工厂:GrapeGardener.java
    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:GrapeGardener.java
     * User:    LavaSoft
     * Date:    2006-12-3
     * Time:    17:51:41
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  添加说明
     */
    public class GrapeGardener implements FruitGardener {
        /**
         * 工厂方法
         *
         * @return 葡萄
         */
        public Fruit factory() {
            Fruit f = new Grape();
            System.out.println("水果工厂(GrapeGardener)成功创建一个水果:葡萄!");
            return f;
        }
    }
     
    1.2.3.3.8 草莓工厂:StrawberryGardener.java
    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:StrawberryGardener.java
     * User:    LavaSoft
     * Date:    2006-12-3
     * Time:    17:53:30
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  添加说明
     */
    public class StrawberryGardener implements FruitGardener {
        /**
         * 工厂方法
         *
         * @return 草莓
         */
        public Fruit factory() {
            Fruit f = new Strawberry();
            System.out.println("水果工厂(StrawberryGardener)成功创建一个水果:草莓!");
            return f;
        }
    }
     
    1.2.3.3.9 测试类(客户端):TestApp.java
    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:TestApp.java
     * User:    LavaSoft
     * Date:    2006-12-3
     * Time:    17:54:48
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  测试类(客户端)
     */
    public class TestApp {
        private FruitGardener f1, f2, f3;
        private Fruit p1, p2, p3;
        private void test() {
            //实力化水果工厂
            f1 = new AppleGardener();
            f2 = new GrapeGardener();
            f3 = new StrawberryGardener();
            //从水果工厂生产水果
            p1 = f1.factory();
            p2 = f2.factory();
            p3 = f3.factory();
        }
        public static void main(String args[]) {
            TestApp test = new TestApp();
            test.test();
        }
    }如要说我现在加一个新的产品,名称叫:香焦,首先我得创建香焦的具体产品,即实现接口,还要创建一个香蕉工厂,那么我在客户端要生产一个香蕉不还得改客户端的代码吗?
      

  6.   

    你看的,应该是抽象工厂方法模式.
    客户端并不是我们C/S架构里面的客户端,它应该只的是模式的使用者.
    楼上的几位应该解释清楚了.目的是,只添加不更改.抽象工厂模式应该可以达到这样的原则.友情up
      

  7.   

    楼上是说: 1.2.3.3.9 测试类(客户端):TestApp.java这个不叫客户端吗?
    我决的应该是客户端。我还是理解不了,在TestApp怎么可能不要动代码呢。之所以说不要修改代码,应该说的是:如果现在要在TestApp里用香蕉,那TestApp里的已有的代码不会被修改,而是直接在后面添加代码。??
      

  8.   

    可以采取配置文件的方式,即把实现类写在配置文件中,下面是个例子,可以参考一下包结构:com
       config
          Config.java
          config.properties (默认配置)
       fruit
          impl
             Apple.java
             Orange.java
             DefaultFruit.java
       Fruit.java
       FruitFactory.java
       FruitTest.java
    config.properties (使用配置)FruitTest.java   测试类
    package com.fruit;public class FruitTest {    public static void main(String[] args) {
            Fruit fruit = FruitFactory.getFruit();
            fruit.printName();
        }
    }Fruit.java   Fruit 的接口
    package com.fruit;public interface Fruit {
        // 输出 Fruit 的名字
        public void printName();
    }Apple.java  Fruit 的一个实现
    package com.fruit.impl;import com.fruit.Fruit;public class Apple implements Fruit {
        public void printName() {
            System.out.println("Hello, I am a apple!");
        }
    }Orange.java  Fruit 的一个实现
    package com.fruit.impl;import com.fruit.Fruit;public class Orange implements Fruit {    public void printName() {
            System.out.println("Hello, I am a Orange!");
        }
    }DefaultFruit.java  Fruit 的默认实现
    package com.fruit.impl;import com.fruit.Fruit;public class DefaultFruit implements Fruit {    public void printName() {
            System.out.println("Hello, I am a default fruit!");
        }
    }FruitFactory.java  产生 Fruit 的工厂
    package com.fruit;import com.fruit.config.Config;public class FruitFactory {
        
        public static Fruit getFruit() {
            Class clazz = null;        
            try {
                // 加载 Class 对象
                  clazz = Class.forName(Config.getInstance().getFruitImpl());
            } catch (ClassNotFoundException e) {
                try {
                    // 加载 Class 失败,即配置中的类不存在,这时使用默认的实现
                      clazz = Class.forName(Config.getInstance().getDefaultFruitImpl());
                } catch (ClassNotFoundException e1) {
                    e1.printStackTrace();
                    return null;
                }
            }
            Fruit fruit = null;
            try {
                fruit = (Fruit)clazz.newInstance();
            } catch (Exception e) {
                e.printStackTrace();            
            }
            return fruit;
        }
    }Config.java   加载配置文件
    package com.fruit.config;import java.io.FileInputStream;
    import java.io.IOException;
    import java.util.Properties;public class Config {
        
        private final static String CONFIG_FILE_NAME = "config.properties";
        private final static String FRUIT_IMPL_KEY = "fruit.impl";
        private final static String DEFAULT_FRUIT_IMPL = "com.fruit.impl.DefaultFruit";
            
        private Properties pro = new Properties();    
        private static Config config = new Config();    
        
        private Config() {
            init();
        }
        
        public static Config getInstance() {
            return config;
        }
        
        public String getFruitImpl() {
            String impl = pro.getProperty(FRUIT_IMPL_KEY);
            if(impl == null || impl.trim().length() == 0) {
                // 如果配置中不存在 Fruit 实现类的配置,则使用默认的实现
                 impl = getDefaultFruitImpl();
                pro.setProperty(FRUIT_IMPL_KEY, impl);
            }
            return impl;
        }
        
        public String getDefaultFruitImpl() {
            return DEFAULT_FRUIT_IMPL;
        }
        
        private void init() {
            try {
                // 从根路径中加载配置文件
                 pro.load(new FileInputStream(CONFIG_FILE_NAME));
            } catch (IOException e) {
                try {
                    // 根路径中若没有找到,则加载 com.fruit.config 中同名配置文件
                      pro.load(Config.class.getResourceAsStream(CONFIG_FILE_NAME));
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }com.fruit.config 目录中的 config.properties 配置文件
    fruit.impl=com.fruit.impl.DefaultFruit应用根路径中的 config.properties 配置文件
    fruit.impl=com.fruit.impl.Apple通过以上的代码,如果以后要增加一个新的水果,只要写一个类实现 Fruit 就行了,如果要使用这个
    新写的类的话,可以把应用根路径中的 config.properties 相关配置改一行就可以了。这样我们就
    降低了耦合程度,原来写好的代码可以一行不动地开始使用新写的类。需要注意的是,不修改是指不对已有的代码进行改动,而不是指不能增加新的实现,这也是面向对象设
    计原则中开-闭原则(OCP)所要求的,即对新增的功能开放,对已有代码
    的修改关闭。
      

  9.   

    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:Fruit.java
     * User:    LavaSoft
     * Date:    2006-12-3
     * Time:    17:25:48
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  水果接口
     */
    public interface Fruit {
        /**
         * 种植
         */
        void plant();
        /**
         * 生长
         */
        void grow();
        /**
         * 收获
         */
        void harvest();
    }
     
    1.2.3.3.2 具体产品苹果Apple.java
    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:Apple.java
     * User:    LavaSoft
     * Date:    2006-12-1
     * Time:    0:47:25
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  水果工厂的产品:苹果
     */
    public class Apple implements Fruit {
        private int treeAge;
        /**
         * 种植
         */
        public void plant() {
            System.out.println("Apple has been planted.");
        }
        /**
         * 生长
         */
        public void grow() {
            System.out.println("Apple is growing...");
        }
        /**
         * 收获
         */
        public void harvest() {
            System.out.println("Apple has been harvested.");
        }
        /**
         * @return 返回树龄
         */
        public int getTreeAge() {
            return treeAge;
        }
        /**
         * 设置树龄
         */
        public void setTreeAge(int treeAge) {
            this.treeAge = treeAge;
        }
    }1.2.3.3.3 具体产品葡萄:Grape.java
    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:Grape.java
     * User:    LavaSoft
     * Date:    2006-12-1
     * Time:    0:36:56
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  水果工厂的产品:葡萄
     */
    public class Grape implements Fruit {
        private boolean seedless;   //是否有籽
        /**
         * 种植
         */
        public void plant() {
            System.out.println("Grape has been planted.");
        }
        /**
         * 生长
         */
        public void grow() {
            System.out.println("Grape is growing...");
        }
        /**
         * 收获
         */
        public void harvest() {
            System.out.println("Grape has been harvested.");
        }
        /**
         * @return 是否有籽
         */
        public boolean getSeedless() {
            return seedless;
        }
        /**
         * 有无籽的赋值方法
         */
        public void setSeedless(boolean seedless) {
            this.seedless = seedless;
        }
        /**
         * 辅助方法
         */
        public static void log(String msg) {
            System.out.println(msg);
        }
    }1.2.3.3.4 具体产品草莓:Strawberry.java
    package com.lavasoft.patterns.factorymethod.ybms;/**
     * Created by IntelliJ IDEA.
     * FileName:Strawberry.java
     * User:    LavaSoft
     * Date:    2006-12-1
     * Time:    0:45:09
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  水果工厂的产品:草莓
     */
    public class Strawberry implements Fruit {
        /**
         * 生长
         */
        public void grow() {
            System.out.println("Strawberry is growing...");
        }
        /**
         * 收获
         */
        public void harvest() {
            System.out.println("Strawberry has been harvested.");
        }
        /**
         * 种植
         */
        public void plant() {
            System.out.println("Strawberry has been planted.");
        }
        /**
         * 辅助方法
         */
        public static void log(String msg) {
            System.out.println(msg);
        }
    }
     
    1.2.3.3.5 水果工厂接口:FruitGardener.java
    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:FruitGardener.java
     * User:    LavaSoft
     * Date:    2006-12-3
     * Time:    17:22:52
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  水果工厂接口
     */
    public interface FruitGardener {
        /**
         * 工厂方法
         *
         * @return 水果
         */
        public Fruit factory();
    }
     
    1.2.3.3.6 苹果工厂:AppleGardener.java
    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:AppleGardener.java
     * User:    LavaSoft
     * Date:    2006-12-3
     * Time:    17:45:29
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  苹果工厂方法
     */
    public class AppleGardener implements FruitGardener {
        /**
         * 工厂方法
         *
         * @return 苹果
         */
        public Fruit factory() {
            Fruit f = new Apple();
            System.out.println("水果工厂(AppletGardener)成功创建一个水果:苹果!");
            return f;
        }
    }
     
    1.2.3.3.7 葡萄工厂:GrapeGardener.java
    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:GrapeGardener.java
     * User:    LavaSoft
     * Date:    2006-12-3
     * Time:    17:51:41
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  添加说明
     */
    public class GrapeGardener implements FruitGardener {
        /**
         * 工厂方法
         *
         * @return 葡萄
         */
        public Fruit factory() {
            Fruit f = new Grape();
            System.out.println("水果工厂(GrapeGardener)成功创建一个水果:葡萄!");
            return f;
        }
    }
     
    1.2.3.3.8 草莓工厂:StrawberryGardener.java
    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:StrawberryGardener.java
     * User:    LavaSoft
     * Date:    2006-12-3
     * Time:    17:53:30
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  添加说明
     */
    public class StrawberryGardener implements FruitGardener {
        /**
         * 工厂方法
         *
         * @return 草莓
         */
        public Fruit factory() {
            Fruit f = new Strawberry();
            System.out.println("水果工厂(StrawberryGardener)成功创建一个水果:草莓!");
            return f;
        }
    }
     
    1.2.3.3.9 测试类(客户端):TestApp.java
    package com.lavasoft.patterns.factorymethod.ybms;
    /**
     * Created by IntelliJ IDEA.
     * FileName:TestApp.java
     * User:    LavaSoft
     * Date:    2006-12-3
     * Time:    17:54:48
     * 《Java与模式》(--阎宏博士著)读书笔记
     * 工厂模式--工厂方法模式--一般性模式(农场应用)
     * ReadMe:  测试类(客户端)
     */
    public class TestApp {
        private FruitGardener f1, f2, f3;
        private Fruit p1, p2, p3;
        private void test() {
            //实力化水果工厂
            f1 = new AppleGardener();
            f2 = new GrapeGardener();
            f3 = new StrawberryGardener();
            //从水果工厂生产水果
            p1 = f1.factory();
            p2 = f2.factory();
            p3 = f3.factory();
        }
        public static void main(String args[]) {
            TestApp test = new TestApp();
            test.test();
        }
    }
    楼主别看代码
    请敲代码
      

  10.   

    据个例子,客户端有调用Operate(int x, int y, char fuhao) ;这个Opreate实现了2个数的加减,然后现在要加入乘除方法,客户端就不用改了,只需要改Operate类里面加方法。新手,我自己的肤浅理解。