设计模式之C#实现(一)--AbstractFactory

Abstract Factory 读书笔记

意图:

       为创建相关的或者相互依赖的对象配置一个借口而不指定他们具体的类。

别名:

       Kit

理解:

       抽象工厂是一种创建型的模式,它为我们创建对象提供了有效地方法,我们不用直接new对象而是可以为创建对象配置一个接口,该接口定义了如何创建对象的方法。我们还知道抽象工厂创建的对象是一个系列的或者是一族的。该模式的最大特点就是将它的具体创建的任务交给了他的子类也就是具体的类,因此我们将创建对象的时间延迟到了它的子类。我们知道,在设计模式(GOF)的书里说了设计模式是为有一定面向对象基础的开发人员准备的。所以我们都应改知道类和类型之间的区别,在现在的编程语言里接口是最为抽象的数据结构,因此我们将我们的抽象工厂里的AbstractFactoy定义成接口也是很自然的。一个这样的工厂可以创建一族产品是什么意思呢?也就是说这一类产品都有相同的父类或者父接口。在这里我不想重复GOF里面的话关于这些对象之间的协作和结果以及带来的影响等等,这些在《Design Patterns Elements of Resable Object-Oriented Software》本书里可以看到。下面我想用C#实现这个模式来供大家参考。

结构:

通过我们的面向对象的知识我们知道一个父类可以标识一个子类的对象,这也是理解这里的关键,我们在程序里将会用一个抽象类的对象表示一个子类的对象。如上图所示,我们现在有我们有一个IabstractFactoy的接口,该接口的职责就是实现创建对象的工作,我们再有两个具体的工厂ConcreteFactory1ConcreteFactory2他们就是具体实现接口中的函数他们实现了这两个方法,当然在具体的应用中可能没有两个具体的工厂,在GOF的书中说过在很多情况下我们并没有工厂的抽象接口,大多数情况都是直接使用具体工厂来实现的,在这里我想力图完整的描述书中的结构所以实现也是一样的。好了下面就是我的代码,这段代码显示了我们是怎么在C#中实现AbstractFactory的。我用一个WinForm来测试结构。

实现代码:

using System;

 

namespace AbstractFactory_Me

{

       public interface IAbstractFactory{

              IAbstractProductA CreateProductA();

              IAbstractProductB CreateProductB();

       }

 

       public interface IAbstractProductA{

              string ShowSelf();

              string ShowOther(IAbstractProductB b);

       }

       public class ProductA1 : IAbstractProductA{

              public ProductA1(){}

              public string ShowSelf(){

                     return this.ToString();

              }

              public string ShowOther(IAbstractProductB b){

                     return b.ToString();

              }

       }

       public class ProductA2 : IAbstractProductA{

              public ProductA2(){}

              public string ShowSelf(){

                     return this.ToString();

              }

              public string ShowOther(IAbstractProductB b){

                     return b.ToString();

              }

       }

 

       public interface IAbstractProductB{

              string ShowSelf();

              string ShowOther(IAbstractProductA a);

       }

       public class ProductB1 : IAbstractProductB{

              public string ShowSelf(){

                     return this.ToString();

              }

              public string ShowOther(IAbstractProductA a){

                     return a.ToString();

              }

       }

       public class ProductB2 : IAbstractProductB{

              public string ShowSelf(){

                     return this.ToString();

              }

              public string ShowOther(IAbstractProductA a){

                     return a.ToString();

              }

       }

 

       public class ConcreteFactory1 : IAbstractFactory{

 

              public IAbstractProductA CreateProductA(){

                     return new ProductA1();

              }

 

              public IAbstractProductB CreateProductB(){

                     return new ProductB1();

              }

 

       }

 

       public class ConcreteFactory2 : IAbstractFactory{

              public IAbstractProductA CreateProductA(){

                     return new ProductA2();

              }

              public IAbstractProductB CreateProductB(){

                     return new ProductB2();

              }

       }

       public class Client{

              public void run(){

                     IAbstractFactory factory1 = new ConcreteFactory1();

                     IAbstractProductA a = factory1.CreateProductA();

                     a.ShowSelf();

                     IAbstractProductB b = factory1.CreateProductB();

                     b.ShowSelf();

                     b.ShowOther(a);

              }

       }

}

我们在测试的WinForm里面放了一个richTextBox1实例,他用来显示结构。

private void Form1_Load(object sender, System.EventArgs e) {

                     this.richTextBox1.Clear();

                     IAbstractFactory factory1 = new ConcreteFactory1();

                     IAbstractProductA a = factory1.CreateProductA();

                     IAbstractProductB b = factory1.CreateProductB();

 

                     this.richTextBox1.AppendText(a.ShowSelf()+"/n");

                     this.richTextBox1.AppendText(b.ShowSelf()+"/n");

                     this.richTextBox1.AppendText(b.ShowOther(a)+"/n");

                     this.richTextBox1.AppendText(a.ShowOther(b)+"/n/n/n");

 

                     this.richTextBox1.AppendText(a.GetType().ToString()+"/n");

                     this.richTextBox1.AppendText(b.GetType().ToString()+"/n");

 

              }

为了清楚的说明问题我们在生成的对象中使用了ShowSelfShowOther的方法用来显示自己和另外一个对象。

书中该例子的C#实现:

 

GOF书中的例子用C#实现的源码:

 

using System;

 

namespace AbstractFactory_Maze{

       using Maze;

 

       public interface AbstractFactory{

              MazeClass MakeMaze();

              Wall MakeWall();

              Room MakeRoom(int n);

              Door MakeDoor(Room oneRoom,Room otherRoom);

       }

 

       public class MazeFactory : AbstractFactory{

              public MazeClass MakeMaze(){

                     return new MazeClass();

              }

              public Wall MakeWall(){

                     return new Wall();

              }

              public Room MakeRoom(int n){

                     return new Room(n);

              }

              public Door MakeDoor(Room oneRoom,Room otherRoom){

                     return new Door(oneRoom,otherRoom);

              }

       }

 

       // this is a client

       public class MazeGame{

              public MazeClass MazeCreate(AbstractFactory factory){

                     MazeClass aMaze = factory.MakeMaze();

                     Room r1 = factory.MakeRoom(1);

                     Room r2 = factory.MakeRoom(2);

                     Door aDoor = factory.MakeDoor(r1,r2);

 

                     aMaze.AddRoom(r1);

                     aMaze.AddRoom(r2);

 

                     r1.SetSide(Direction.North,factory.MakeWall());

                     r1.SetSide(Direction.East,aDoor);

                     r1.SetSide(Direction.South,factory.MakeWall());

                     r1.SetSide(Direction.West,factory.MakeWall());

 

                     r2.SetSide(Direction.North,factory.MakeWall());

                     r2.SetSide(Direction.East,factory.MakeWall());

                     r2.SetSide(Direction.South,factory.MakeWall());

                     r2.SetSide(Direction.West,aDoor);

 

                     return aMaze;

              }

       }

 

}

 

namespace Maze{

       using System.Collections;

 

       public class MapSite{

              public virtual void Enter(){}

       }

 

       public enum Direction {North,South,East,West}

 

       public class Room : MapSite{

              public string Print(){

                     string result = "";

                     for(int i = 0 ;i<=3;i++){

                            switch(i){

                                   case (int)Direction.East:{

                                          result += "East is:"+this.GetSide(Direction.East)+"/t";

                                          break;

                                   }

                                   case (int)Direction.North:{

                                          result += "North is:"+this.GetSide(Direction.North)+"/t";

                                          break;

                                   }

                                   case (int)Direction.South:{

                                          result += "South is:"+this.GetSide(Direction.South)+"/t";

                                          break;

                                   }

                                   case (int)Direction.West:{

                                          result += "West is:"+this.GetSide(Direction.West)+"/t";

                                          break;

                                   }

                            }

                     }

                     return result;

              }

 

              public Room(int n){

                     this.m_roomNumber = n;

              }

 

              public MapSite GetSide(Direction dir){

                     return this.m_sides[(int)dir];

              }

 

              public void SetSide(Direction dir,MapSite mapSite){

                     this.m_sides[(int)dir] = mapSite;

              }

 

              public override void Enter(){}

              private MapSite[] m_sides = new MapSite[4];

              int m_roomNumber;

       }

 

       public class Wall : MapSite{

              public Wall(){}

              public override void  Enter(){}

       }

 

       public class Door : MapSite{

              public Door(Room oneRoom,Room otherRoom){}

              public override void Enter(){}

              public Room oneRoom{

                     get{return this.m_oneRoom;}

                     set{this.m_oneRoom = value;}

              }

              private Room m_oneRoom;

              public Room otherRoom{

                     get{return this.m_otherRoom;}

                     set{this.m_otherRoom = value;}

              }

              private Room m_otherRoom;

              private bool m_isOpen;

              public bool IsOpen{

                     get{return this.m_isOpen;}

                     set{this.m_isOpen = value;}

              }

       }

 

       public class MazeClass{

              public MazeClass(){}

 

              public string Print(){

                     string result = "";

                     for(int i = 0; i<=this.m_Maze.Count-1;i++){

                            result +=this.RoomNumber(i).Print()+"/n";

                     }

                     return result;

              }

 

              public void AddRoom(Room room){

                     m_Maze.Add(room);

              }

 

              public Room RoomNumber(int roomNumber){

                     return (Room)this.m_Maze[roomNumber];

              }

 

              private ArrayList m_Maze = new ArrayList();

 

       }

}

 

              private void Form1_Load(object sender, System.EventArgs e) {

                     AbstractFactory factory = new MazeFactory();

                     MazeGame game = new MazeGame();

                     MazeClass aMaze = game.MazeCreate(factory);

                     this.richTextBox1.AppendText(aMaze.Print());

 

              }

 

以下为输出结果:

North is:Maze.Wall      South is:Maze.Wall      East is:Maze.Door       West is:Maze.Wall 

North is:Maze.Wall      South is:Maze.Wall      East is:Maze.Wall       West is:Maze.Door

 

希望本文可以对即将要学习设计模式或者还有疑惑的人提供帮助,由于作者的能力有限如果文中又不对的地方请指出,或者联系我(wu_jian830@hotmail.com)谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值