C#描述设计模式(3):创建者模式学习心得

来源:互联网 发布:手机端淘宝全球购入口 编辑:程序博客网 时间:2024/05/21 09:15

创建者模式学习心得

 适用场景:


某个东西需要由其他的东西组合而成。

如中国移动的套餐,套餐A是由短信包1和长话包2组成的;套餐B是由短信包2和长话包3组成的。

适合应付这样的变化:如果套餐的数目不确定,并且里面的包的数目和类别也不确定。

比如中国移动的套餐随着时间的变化,需要不断变化,并且不断推出新的套餐品种。



本文的例子场景:

搭配衣服场景。
一个人要去找工作,首先要选择一个合适的套装(Suit)。

而套装又是由上衣(Jacket)、裤子(pants)和鞋子(Shoe)组成的。

他要根据不同的工作性质选择不同的衣服。

涉及对象:

1。需要穿衣服的人:Client

2。指导它穿哪套套装的对象:Director

3。A套装的构造者:ABuilder,B套装的构造者:BBuilder,C套装的构造者:CBuilder
和他们继承的接口:IBuilder

4。套装:Suit

5。上衣:Jacket、裤子:pants、鞋子:shoe

类的关系图:图1



具体实现方法:

1。Client的职责是选择一种套装。client需要输入他所选择的套装类型。
class Client
    
{
        
static void Main(string[] args)
        
{
            
//test BuilderPattern
            Director director = new Director();
            IBuilder builder;
            Console.WriteLine(
"input your choice : A , B or C?");
            
string Signal = Console.ReadLine();
            builder 
= director.ConstructSuit(Signal);
            Suit suit
=builder.GetSuit();
            suit.Show();

            Console.ReadLine();
        }

    }



2。Director的职责是找出可以创建该套装的“创建者”。
他是沟通Client的需求和“创建者”工作的一个中间环节。 
 public class Director
    
{
        
public IBuilder ConstructSuit(string Signal)
        
{
            
switch (Signal)
                    
{
                        
case "A"return new ABuilder(); }
                        
case "B"return new  BBuilder();  }
                        
case "C"return new  CBuilder();  }
                        
defaultreturn null;
                    }


           
            
        }

    }





3。ABuilder、BBuilder、CBuilder均实现IBuilder的接口,
用来创建A种的Suit、B种Suit、C种Suit。
public interface IBuilder
    
{
        Suit GetSuit();
    }


    
public class ABuilder : IBuilder
    
{
        
public Suit GetSuit()
        
{
            Jacket jacketA 
= new Jacket("A");
            Pants pantsA 
= new Pants("A");
            Shoe shoeA 
= new Shoe("A");

            Suit suitA 
= new Suit(jacketA, pantsA, shoeA);
            
return suitA;
        }

    }

    
public class BBuilder : IBuilder
    
{
        
public Suit GetSuit()
        
{
            Jacket jacketB 
= new Jacket("B");
            Pants pantsB 
= new Pants("B");
            Shoe shoeB 
= new Shoe("B");

            Suit suitB 
= new Suit(jacketB, pantsB, shoeB);
            
return suitB;
        }

    }


    
public class CBuilder : IBuilder
    
{
        
public Suit GetSuit()
        
{
            Jacket jacketC 
= new Jacket("C");
            Pants pantsC 
= new Pants("C");
            Shoe shoeC 
= new Shoe("C");

            Suit suitC 
= new Suit(jacketC, pantsC, shoeC);
            
return suitC;
        }

    }


4。套装类。他的职责是规范一个套装应该有的三个部分,并且根据这三个部分创建出套装
 public class Suit
    
{
        Jacket theJacket;
        Pants thePants;
        Shoe theShoe;


        
public Suit(Jacket jacket, Pants pants, Shoe shoe)
        
{
            theJacket 
= jacket;
            thePants 
= pants;
            theShoe 
= shoe;
        }

        
public void Show()
        
{
            theJacket.show();
            thePants.Show();
            theShoe.Show();

        }

    }

5。裤子、衣服和鞋子,均是最基本的构成,职责是通过传入的 参数构造出一个自己:
 public class Jacket
    
{
        
public string JacketType;
        
public Jacket(string jacketType)
        
{
            JacketType 
= jacketType;
        }

        
public void show()
        
{
            Console.WriteLine(
"I'm " + JacketType + " jacket");
        }

    }

    
public class Pants
    
{
        
public string PantsColor;
        
public Pants(string pantsColor)
        
{
            PantsColor 
= pantsColor;
        }

        
public void Show()
        
{
            Console.WriteLine(
"I'm " + PantsColor + " color Pants");
        }

        
    }

    
public class Shoe
    
{
        
public string ShoeSize;
        
public Shoe(string shoeSize)
        
{
            ShoeSize 
= shoeSize;
        }

        
public void Show()
        
{
            Console.WriteLine(
"I'm Shoe of" + ShoeSize);
        }

    }



效果:

按照传统的思维,我们会这样处理这个问题:

创建一个Suit的父类,然后不断的继承它,从而创造出A、B、C三种套装。

client根据自己的需求,来选择实例化不同的套装。

但是这样有什么缺点呢?

1。使用创建者模式的时候,Client并不必知道Suit这个东西,它只面对Director,

它只需要知道到底是A、B还是C。他不用关心到底是Suit还是Coad,或者是其他什么东西。

如果说在构造套餐之外,有其他的需求是和A、B、C的选择相关的,就可以体现出创建者模式的优势。

比如,A表示“严肃”系列,适合应聘行政工作;B表示“休闲”系列,适合应聘美工。

Client在对Director作出A、B的选择后,除了获得了一个合适的Suit,还需要获得一份“面试指导”。

这时候Director就可以调用其他对象了

2。builder之间更加松耦合。相对于传统的方法,它和Suit的关系是“使用”,而不是“继承”。

3。构造的过程可以更加精细控制。比如说,某种Suit不需要shoe了,它只要有jacket和pants就可以了。
 
它可以先构造jacket,也可以先构造shoe。。。

4。构建代码和表现代码分离。构造是在Builder类里面实现的,而表现是由suit实现的。

这样实现了控制和表现的分离。

5。不同的suit只是不同jacket、pants和shoe的排列组合而已,从概念上说不是继承的关系。


补充说明:

和工厂模式的区别:

1。builer的重点是在不同的请求下,给出不同的排列组合。

Factory的重点是在不同的请求下,给出不同类的实例。

2。Builder不需要一个抽象的Suit。而用工厂就需要了。

附:用工厂实现这个需求的类图:图2


这样的场景比较适合使用工厂:一个人要选择面试的裤子:它如果选A就给Apants,选B就给Bpants。。。


代码的优化:

其中,Director可以采用映射生成一个实例
这样的话,Director中就不需要出现A、B的字眼了。
 public class Director
    
{
        
public IBuilder ConstructSuit(string Signal)
        
{
            
//switch (Signal)
            
//        {
            
//            case "A": { return new ABuilder(); }
            
//            case "B": { return new  BBuilder();  }
            
//            case "C": { return new  CBuilder();  }
            
//            default: return null;
            
//        }

            
return (IBuilder)Assembly.Load("ConsoleApplication1").CreateInstance("BuilderPattern." + Signal + "Builder");
            
        }

    }
 


模式应用:

这个模式的应用范围非常广。这种类似于“套餐”的 都可以应用。

1。用户页面的定制。

2。自动生成网站系统中的页面布局。如果可以做成这样的话,那网站只需要一个页面 了
根据它的需求定制它的控件就可以了。

3。DataList的建造

4。用户订阅不同的信息,其实也是套餐。