前一篇文章,介绍了工厂方法,并且,探讨了下工厂方法的不足之处:

及我们知道,在工厂方法中,每个 Creator,只是创建单一的实例,那对于一次要创建n多不同的类实例的情况呢?
及,如果我们要实现这样的方法呢?:
using System;
using System.Collections.Generic;
using System.Text;

namespace 工厂方法
{
    public interface ICreator<T> where T : IDomain
    {
        ISpeciality<T> CreaterSpeciality( );
        //这里带上其他的类的创建方法
    }
}

抽象工厂,为我们很好的解决了这个问题。

如在一个农场中,会种植水果和蔬菜。而蔬菜和水果的种类,又因地域的不同而不同,如:南方的农民种植的水果为荔枝,蔬菜为苦瓜,北方的农民种植的水果是红枣,蔬菜是大白菜。一个农场的农民,农场主不可能要求他的工人在会种植一样东西,需要都能够种植。用程序来解释,如下:

农民接口:

using System;
using System.Collections.Generic;
using System.Text;

namespace 抽象工厂
{
    public interface 农民接口
    {
        蔬菜接口 种植蔬菜();

        水果接口 种植水果();

    }
}

 

水果接口:

using System;
using System.Collections.Generic;
using System.Text;

namespace 抽象工厂
{
    /// <summary>
    /// 水果的接口
    /// </summary>
    public interface 水果接口
    {
        /// <summary>
        /// 水果的味道
        /// </summary>
        /// <returns></returns>
        string 味道();
        /// <summary>
        /// 水果生长周期
        /// </summary>
        /// <returns></returns>
        int 水果生长周期();

        /// <summary>
        /// 水果生长区域
        /// </summary>
        /// <returns></returns>
        string 生长区域();
        
    }
}

蔬菜接口:

using System;
using System.Collections.Generic;
using System.Text;

namespace 抽象工厂
{
    /// <summary>
    /// 蔬菜接口
    /// </summary>
   public interface 蔬菜接口
    {
       /// <summary>
       /// 蔬菜生长区域
       /// </summary>
       /// <returns></returns>
       string 生长区域();

       /// <summary>
       /// 一棵种子是否只长一个果实
       /// </summary>
       /// <returns></returns>
       bool 一棵种子是否只长一个果实();
    }
}

各种水果类:

using System;
using System.Collections.Generic;
using System.Text;

namespace 抽象工厂
{
    /// <summary>
    /// 荔枝类 南方生产的水果
    /// </summary>
    public class 荔枝 : 水果接口
    {
        public string 味道()
        {
            return "荔枝非常的甜";
        }

        public int 水果生长周期()
        {
            return 1;
        }
        public string 生长区域()
        {
            return "南方";
        }
    }
}

using System;
using System.Collections.Generic;
using System.Text;

namespace 抽象工厂
{
    public class 红枣 : 水果接口
    {
        public string 味道()
        {
            return "红枣有点甜";
        }

        public int 水果生长周期()
        {
            return 1;
        }
        public string 生长区域()
        {
            return "北方";
        }
    }
}

各种蔬菜类:

using System;
using System.Collections.Generic;
using System.Text;

namespace 抽象工厂
{
    public class 大白菜 : 蔬菜接口
    {
        public string 生长区域()
        {
            return "北方";
        }

        public bool 一棵种子是否只长一个果实()
        {
            return true;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Text;

namespace 抽象工厂
{
    public class 苦瓜 : 蔬菜接口
    {
      public  string 生长区域()
        {
            return "南方";
        }

        public bool 一棵种子是否只长一个果实()
        {
            return false;
        }
    }
}

农民类:

using System;
using System.Collections.Generic;
using System.Text;

namespace 抽象工厂
{
    public class 南方农民 : 农民接口
    {
        public 蔬菜接口 种植蔬菜()
        {
            return new 苦瓜();
        }

        public 水果接口 种植水果()
        {
            return new 荔枝();
        }
    }
}

using System;
using System.Collections.Generic;
using System.Text;

namespace 抽象工厂
{
    public class 北方农民 : 农民接口
    {
        public 蔬菜接口 种植蔬菜()
        {
            return new 大白菜();
        }

        public 水果接口 种植水果()
        {
            return new 红枣();
        }
    }
}

使用的时候:

  private void button1_Click(object sender, EventArgs e)
        {
            农民接口 一个农民 = new 南方农民();
            水果接口 水果 = 一个农民.种植水果();
            蔬菜接口 蔬菜 = 一个农民.种植蔬菜();
        }

这样,南方的农民就可以同时种植南方的水果和南方的蔬菜了,也就解决了一个农民只能够种植一种东西的情况,也就是解决了工厂方法的问题。

 

抽象工厂 和 建造者buileder的不同:

首先,抽象工厂返回的是一个完完全全的产品对象,客户端 可以根据这些产品对象,再去组装出更加复杂的产品对象。

而建造者,返回的不是一个完整的产品对象,客户端需要自己在去把产品的各个部件在组装起来。

如果两个模式结合起来用,情况可以这样:

如在一个游戏中,如:西山居 开发的 剑侠情缘 来说,一张地图上,需要建立房子,道路,路标,广告牌等等,

一张地图,需要创建这些东西,而这些房子呀什么的,又有不同的风格,建造者+抽象工厂,就可以能够满足这个地图的创建(呵呵,对于该游戏到底是怎么弄的,我是不知道,自己乱想的)

上面的程序,用的中文表示,呵呵,一是测试vs里面能够用中文不,二是这样看起来容易点。

posted on 2007-12-14 16:35  颜昌钢  阅读(194)  评论(0编辑  收藏  举报