java工厂模式,懂的人进

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java工厂模式,懂的人进相关的知识,希望对你有一定的参考价值。

在JAVA中。工厂模式在我们实际写代码的时候,什么情况下会用到呢。
大家说的不一样。对工厂模式的认识也不一样。踊跃参加,对自己有好处的。详细点。
谢谢

举两个例子以快速明白Java中的简单工厂模式:

女娲抟土造人
话说:“天地开辟,未有人民,女娲抟土为人。”女娲需要用土造出一个个的人,但在女娲造出人之前,人的概念只存在于女娲的思想里面。
女娲造人,这就是简单工厂模式的应用。

  首先,在这个造人的思想里面,有几个重要的角色:女娲本身、抽象的人的概念和女娲所造出的一个个具体的人。
  1.)女娲是一个工厂类,也就是简单工厂模式的核心角色。
2.)具休的一个个的人,包括张三,李四等。这些人便是简单工厂模式里面的具体产品角色
  3.)抽象的人是最早只存在于女娲的头脑里的一个想法,女娲按照这个想法造出的一个个具体的人,便都符合这个抽象的人的定义。换言之,这个抽象的想法规定了所有具体的人必须都有的接口(特征或者功能)
   其UML类图出下所示:
    
理解了上面的这些东西,再来理解下面的例子,对照理解,相信看完这篇文章,便对java简单工厂模式有一个很好的理解:

有一个农场公司,专门向市场销售各类水果,在这个系统里需要描述下列水果:
     葡萄 Grape
     草莓 Stuawberry
     苹果 Apple
水果与其他植物不同,最终可以采摘食用,那么一个自然的做法是建立一个各种水果都适用的接口,以便与其他农场里的植物区分开来,

此时,则是为水果类声明了一个接口,表现在代码上:

1 public interface Fruit
2 // 生长
3 void grow();
4 // 收获
5 void harvest();
6 // 种植
7 void plant();
8
9
10

水果接口规定出所有的水果必须实现的接口,包括任何水果类必须具备的方法plant(),grow(),和harvest();

Apple类是水果类的一种,因此它实现了水果接口所声明的所有方法。另处,由于苹果是多年生植物,因此多出一个treeAge性质,描述苹果的树龄。代码如下所示:

package fac;

public class Apple implements Fruit // 通过implements实现接口Fruit
private int treeAge;

public void grow()
log( " Apple is growing " );


public void harvest()
log( " Apple has been harvested " );


public void plant()
log( " Apple ha been planted " );


public static void log(String msg)
System.out.println(msg);


public int getTreeAge()
return treeAge;


public void setTreeAge( int treeAge)
this .treeAge = treeAge;



同理,葡萄 Grape:

package fac;

public class Grape implements Fruit
private boolean seedless;
public void grow()
log("Grape is growing.");


public void harvest()
log("Grape has been harvested");


public void plant()
log("Grape ha been planted");


public static void log(String msg)
System.out.println(msg);


public boolean isSeedless()
return seedless;


public void setSeedless(boolean seedless)
this.seedless = seedless;




草莓 Stuawberry:

package fac;

public class Strawberry implements Fruit
public void grow()
log("Strawberry is growing");


public void harvest()
log("Strawberry has been harvested");


public void plant()
log("Strawberry has been planted");


public static void log(String msg)
System.out.println(msg);



农场园丁也是系统的一部分,由一个类来代表,FruitGardener类,代码如下:

package fac;

public class FruitGardener
public static Fruit factory(String which)throws Exception
if(which.equalsIgnoreCase("apple"))
return new Apple();
else if(which.equalsIgnoreCase("strawberry"))
return new Strawberry();
else if (which.equalsIgnoreCase("grape"))
return new Grape();
else
throw new Exception("Bad fruit request");



这时有人来果园玩,和园丁说,给我们介绍下你的水果吧。于是园丁:

package fac;

public class People

public static void main(String[] args) throws Exception
FruitGardener fg=new FruitGardener();
Fruit ap=fg.factory("Apple");
ap.grow();
Fruit gp=fg.factory("Grape");
gp.plant();

Fruit dd=fg.factory("ddd");//抛出Bad fruit request异常




(注:以上代码在JDK5.0,Myeclise3.2下编译通过)

类比两个例子,园丁就相当于女娲,而水果就相当于具体的人,接口水果类就相当于存在于类女娲思想里的人的抽象概念。

由以上两个例子可得出,简单工厂模式需要由以下角色组成:
      接口
接口的实现类(简单工厂模式里面的具体产品角色)
工厂

理解了以下两个例子,再来看第三个例子:
注意对比以下三个实例的不同
实例1:

package org.jzkangta.factorydemo01;
//定义接口
interface Car
public void run();
public void stop();

//具体实现类
class Benz implements Car
public void run()
System.out.println("Benz开始启动了。。。。。");

public void stop()
System.out.println("Benz停车了。。。。。");


//具体实现类
class Ford implements Car
public void run()
System.out.println("Ford开始启动了。。。");

public void stop()
System.out.println("Ford停车了。。。。");


//工厂
class Factory
public static Car getCarInstance()
return new Ford();


public class FactoryDemo01

public static void main(String[] args)
Car c=Factory.getCarInstance();
c.run();
c.stop();





实例二:

package fac;

//定义接口
interface Car
public void run();
public void stop();

//具体实现类
class Benz implements Car
public void run()
System.out.println("Benz开始启动了。。。。。");

public void stop()
System.out.println("Benz停车了。。。。。");



class Ford implements Car
public void run()
System.out.println("Ford开始启动了。。。");

public void stop()
System.out.println("Ford停车了。。。。");


//工厂
class Factory
public static Car getCarInstance(String type)
Car c=null;
if("Benz".equals(type))
c=new Benz();

if("Ford".equals(type))
c=new Ford();

return c;



public class FactoryDemo02

public static void main(String[] args)
Car c=Factory.getCarInstance("Benz");
if(c!=null)
c.run();
c.stop();
else
System.out.println("造不了这种汽车。。。");






实例三:

interface Car
public void run();
public void stop();


class Benz implements Car
public void run()
System.out.println("Benz开始启动了。。。。。");

public void stop()
System.out.println("Benz停车了。。。。。");



class Ford implements Car
public void run()
System.out.println("Ford开始启动了。。。");

public void stop()
System.out.println("Ford停车了。。。。");



class Toyota implements Car
public void run()
System.out.println("Toyota开始启动了。。。");

public void stop()
System.out.println("Toyota停车了。。。。");



class Factory
public static Car getCarInstance(String type)
Car c=null;
try
c=(Car)Class.forName("org.jzkangta.factorydemo03."+type).newInstance();//利用反射得到汽车类型 
catch (InstantiationException e)
// TODO Auto-generated catch block
e.printStackTrace();
catch (IllegalAccessException e)
// TODO Auto-generated catch block
e.printStackTrace();
catch (ClassNotFoundException e)
// TODO Auto-generated catch block
e.printStackTrace();


return c;


public class FactoryDemo03

public static void main(String[] args)
Car c=Factory.getCarInstance("Toyota");
if(c!=null)
c.run();
c.stop();
else
System.out.println("造不了这种汽车。。。");






对比三个实例:
实例一,虽然实现了简单工厂,但每次只能得到一种汽车,如果我们想换一种,就得修改工厂,太不方便,而实例二则改变了这种情况,便得我们可以按照我们的需要更换汽车,但我们所更换的汽车必须是实现类中有的,如果我们想要增加一种汽车的时候,我们还是得更改工厂,通过改进,实例三利用反射机制,得到汽车类型,这样当我们需要增加一种新的汽车时,就无需要再修改工厂,而只需要增加要实现的类即可。也就是说要增加什么样的汽车直接增加这个汽车的类即可,而无需改变工厂。从而达到了工厂分离的效果。
参考技术A 1、工厂模式是一些固化的代码操作,可以减少代码的反复定义提高代码的复用性。
2、如单例模式,通过它的操作可以保证一个类在内存中只会有一个对象存在。
参考技术B 纯个人观点:工厂模式就是一个拥有相同功能但是实现方法却不同的一个实例的集合体,每一次要调用这个功能的时候,都需要去工厂中取得实例来实现这个功能。这些实例都是单例模式的,方便容器进行管理。比如你要做的事情是去超市买东西。不同大小的购物袋可以买不同数量的东西。所有这些大大小小的塑料袋所存放的盒子就相当于一个工厂,每次去“买东西时”我们根据本次要买物品的多少去盒子(工厂)里拿一个袋子(实例),买完东西后,又将袋子放回盒子。

不知道是否对你有帮助呢?追问

你的观点还不错。不过有些地方我还是不太明白。
为什么----->这些实例都是单例模式的,

为什么是单例就会----->方便容器进行管理。

追答

如果你用多例的,那系统使用过程中会无限创建对象,这些对象如果不能及时释放,会造成内存溢出引起系统崩溃

本回答被提问者采纳

设计模式之策略模式&简单工厂模式

   学习设计模式已经有非常长一段时间了,事实上先前已经敲过一遍了。可是老认为没有学到什么,认识也不够深刻。如今趁着重构机房,再又一次来过,也不晚。

  事实上在敲了机房之后,看看模式,事实上,曾经非常难理解。非常难看懂的代码一眼就能够看懂了,趁着有点感觉了。早点收获吧。

  简单工厂模式:

  简单地说简单工厂模式:非常easy变化的地方,就能够用到简单工厂模式。

  实例:

  举个样例:我们在逛商场时。正好商场促销,各种优惠活动:有满300返100 ,有打8折的、抽奖等等吧。

  促销来讲,各种优惠活动事实上就是变化。

  再举个样例:我们在买早餐的时候。早餐店里琳琅满目,但不管是谁来这家商店买都系,营业员问你须要什么,他就知道给你拿什么东西。我们须要的东西就是变化。

  浅谈:

  简单工厂模式就是通过传入的数据返回几种可能类宏的一种类的实例。但这几种类通常会有一个共同特点就是:这几种类有一个共同的父类和共同的方法。但每一个方法被容不同。并且依据不同的数据进行优化。

  深入:

  上述是浅谈,实质:面对这些变化,面向对象的思想就是封装这些变化。封装变化之后,则可添加它的可扩展性,不会再改动曾经的类了。

  简单工厂模式结构图:

技术分享

  实现商场促销:

  父类:

<span style="background-color: rgb(204, 204, 204);"><strong>    abstract class CashSuper//父类。一个抽象还是,封装
    {
        public abstract double acceptCash(double money);
    }</strong></span>

  各个子类:

    class CashNormal :CashSuper//各个实例化的对象。实现了多态
    {
        public override double acceptCash(double money)//实现父类中的方法。并各个不同的类之间都有差异
        {
            return money;
        }
    }
    class CashRebate:CashSuper
    {
        private double moneyRebate = 1d;
        public CashRebate(string moneyRebate)
        {
            this.moneyRebate = double.Parse(moneyRebate);
        }
        public override double acceptCash(double money)
        {
            return money * moneyRebate;
        }
    }
    class CashReturn:CashSuper
    {
        private double moneyCondition = 0.0d;
        private double moneyReturn = 0.0d;
        public CashReturn (string moneyCondition,string moneyReturn)
        {
            this.moneyCondition = double.Parse(moneyCondition);
            this.moneyReturn = double.Parse(moneyReturn);
        }
        public override double acceptCash(double money)
        {
            double result = money;
            if (money >= moneyCondition)
                result = money - Math.Floor(money / moneyCondition) * moneyReturn;

            return result;
        }

    }

  工厂模式:

    //简单工厂模式
    class CashFactory//简单工厂模式实现了。将选择放在了业务层。而不是界面层
    {
        public static CashSuper createCashAccept(string type)
        {
            CashSuper cs = null;//定义了一个父类的类型
            switch (type)
            {
                case"正常收费":
                    cs = new CashNormal();//实例化的是各个子类对象
                    break;
                case"满300返100":
                    CashReturn cr1 = new CashReturn("300", "100");
                    break;
                case"打8折":
                    CashRebate cr2 = new CashRebate("0.8");
                    break;
            }
            return cs;
        }
    }

 界面层:

        private void button1_Click(object sender, EventArgs e)
        {
            //简单工厂模式-------------------------------------------------------------------
            CashSuper csuper = CashFactory.createCashAccept(cbxType.SelectedItem.ToString());//简单工厂模式的写法,client认识两个类,CashSuper和CashFactory。再简单工厂模式中就已经实例出了各个子类对象
            double totalPrices = 0d;
            totalPrices = csuper.acceptCash(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
            total = total + totalPrices;
            lbxList.Items.Add("单位价格" + txtPrice.Text + "数量:" + txtNum.Text + "" + cbxType.SelectedItem + "合计:" + totalPrices.ToString());
            label4.Text = total.ToString();

        }

  我们都知道,商店不是一直都有促销的。也不一定今年这这样的促销。明年还是这样的,事物都是在随着时间变化的。假设每次更改打折额度和返利额度,每次都要维护或扩展收费方式,都要修改工厂。一直代码徐又一次编译部署。这要就非常糟糕了,面对算法的市场变动。就须要策略模式了。

  策略模式:

  样例:

  商店里促销每年须要更改打折额度和返利额度。

 结构图:

技术分享

  闲谈:

  事实上策略模式定义了算法家族。分别封装起来。让他们之间能够相互取代,此模式让算法的变化,不会影响到使用算法的客户。全部这些算法完毕的都是同样的工作,仅仅是实现不同,他能够用同样的方法调用全部的算法。降低了算法类和使用算法类之间的耦合。

  深入:

  简单工厂来生成算法对象,算法是随时都可能互相替换,这就是变化点。封装变化点。

  实现商店促销:

  前面的父类和个促销子类不须要改动:

  策略模式代码:

    class CashContext//用一个CashContext来配置,维护一个对Strategy对象的引用。
    {
        CashSuper cs=null;
        public CashContext(string type)//应用了简单工厂模式将父类实例化的对象(不同的子类)
        {
            switch (type)//给一个值,来选择不同的对象。传入详细的策略对象
            {
                case"正常收费":
                    CashNormal cs0=new CashNormal();
                    cs=cs0;
                    break;
                case"满300返100":
                    CashReturn cr1=new CashReturn ("300","100");
                    cs=cr1;
                    break;
                case"打8折":
                    CashRebate cr2=new CashRebate ("0.8");
                    cs=cr2;
                    break;
            }
        }
        public double GetResult(double money)
        {
            return cs.acceptCash(money);
        }
    }

  界面代码:

        private void button1_Click(object sender, EventArgs e)
        {


            //策略模式和简单工厂模式结合----------------------------------------------------
            CashContext csuper = new CashContext(cbxType.SelectedItem.ToString());//client仅仅认识CashContext即可了,纯如详细的策略对象
            double totalprices = 0d;
            totalprices = csuper.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
            total = total + totalprices;
            lbxList.Items.Add("单位价格:" + txtPrice.Text + "数量:" + txtNum.Text + " " + cbxType.SelectedItem + "合计:" + totalprices.ToString());
            label4.Text = total.ToString();
        }

  以上就是策略模式和简单工厂模式的结合了,简单工厂模式事实上说简单一点就是:一个类创造实例的过程。策略模式:策略随时有可能互相替换。

  

  











以上是关于java工厂模式,懂的人进的主要内容,如果未能解决你的问题,请参考以下文章

C#设计模式-工厂模式

关于Java开发的面试经验总结,90%的人看完都说好

设计模式之策略模式&amp;简单工厂模式

JAVA设计模式——工厂模式简单工厂模式工厂方法模式抽象工厂模式

java抽象工厂的使用意图是啥?

设计模式之策略模式&amp;简单工厂模式