建造者模式、组合模式和装饰者模式

今天将和大家一起讨论建造者模式、组合模式和装饰者模式。

先来讨论建造者模式,字里行间很容易明白这是一种对象创建型模式,一般对象的创建是由本身抽象实例化本身,在这里需要通过另外种角色建造者角色去帮我们创建。这是为什么呢?因为在现实系统中,我们遇到的对象往往是很复杂的对象。该对象由很多子对象组成,并且这些子对象的创建步骤是一样,只是它们的创建细节不一样,我们怎么解决该类问题呢!这就要求我们使用“封装机制”来隔离出“复杂对象的各个部分”的变化,这就是要讨论的建造者模式。

结构示意图如下:

 

建造者模式中的角色:

指导角色:对象创建的指导者,负责将客户的请求传给建造者,控制建造者怎样创建复杂对象。

抽象建造者角色:复杂对象创建者,提供对象创建模板。

具体建造者角色:实现复杂对象创建,提供对象创建细节,并向客户返回复杂对象。

示意代码:

抽象建造者:

    /// <summary>

    /// 抽象构造者,制定了复杂对象的构造步骤

    /// </summary>

    public abstract class AbstractBuilder

    {

        public abstract void BuilderPart1();

        public abstract void BuilderPart2();

        public abstract Food GetFood();

}

具体建造者:

    /// <summary>

    /// 具体建造者,实现了复杂对象具体构造细节

    /// </summary>

    public class FoodBuilder:AbstractBuilder

    {

        private Food food = new Food();

        public override void BuilderPart1()

        {

            food.AddFood("a", "1");

        }

 

        public override void BuilderPart2()

        {

            food.AddFood("b", "2");

        }

 

        public override Food GetFood()

        {

            return food;

        }

    }

复杂对象:

    /// <summary>

    /// 复杂对象

    /// </summary>

    public class Food

    {

        private Dictionary<string, string> ht = new Dictionary<string, string>();

 

        public void AddFood(string name, string price)

        {

            ht.Add(name, price);

        }

 

        public void Show()

        {

            foreach (KeyValuePair<string, string> kv in ht)

            {

                Console.WriteLine(kv.Key + ":" + kv.Value);

            }

        }

    }

指挥者:

    /// <summary>

    /// 复杂对象构造控制者

    /// </summary>

    public class Director

    {

        public Director()

        {

 

        }

 

        public Food Construct(AbstractBuilder ab)

        {

            ab.BuilderPart1();

            ab.BuilderPart2();

            return ab.GetFood();

        }

    }

客户端示意性代码:

class Client

    {

        static void Main(string[] args)

        {

            AbstractBuilder ab = new FoodBuilder();

            Director d = new Director();

            Food food=d.Construct(ab);

            food.Show();

            Console.ReadLine();

        }

 

    }

 

复杂对象创建时序图:

 

总结:

建造者模式向客户端隐藏了复杂对象的构造细节,符合设计原则开-闭原则。

 

 

 

 

 

 

 

 

 

 

接下来我们讨论组合模式(Composite)

在学习ASP.NET的时候,我们经常会碰到页面生命周期的问题。相信大家用户控件都用过,

当服务器渲染用户控件的时候,都会调用其中子空间的渲染方法,在用户(我们)看来,使用用户控件这种复杂元素就像使用简单元素一样方便,这无形之中就用到了常用的设计思想组合模式。组合模式的作用:就是封装复杂元素的复杂性,提供和简单元素一样的访问接口。

结构示意图:

 

组合模式涉及的角色:

抽象构件:规范了简单对象和复杂对象共同的接口。

简单对象:实现了抽象构件。

复杂对象:实现了抽象构件,并且提供管理简单对象的方法。

这里组合对象既实现了一般构件的方法,并且拥有复杂构件的维护接口,这属于组合模式安全式实现,如果将这部分接口提取到抽象构件里面,那么简单构件也拥有这部分功能,这是组合模式的透明式实现,但是这种设计有点不合理。

组合模式安全模式实现示意代码:

抽象构件:

    /// <summary>

    /// 抽象构件 定义了简单构件和复杂构件统一的访问接口

    /// </summary>

    public abstract class AbstractComponent

    {

        public abstract void Render();

}

 

简单构件:

    /// <summary>

    /// 简单构件

    /// </summary>

    public class SampleComponent:AbstractComponent

    {

 

        public override void Render()

        {

            //render code

        }

}

 

复杂构件:

    /// <summary>

    /// 组合构件,聚合了简单构件

    /// </summary>

    public class Composite:AbstractComponent

    {

        private List<AbstractComponent> sl=new List<AbstractComponent>();

        public override void Render()

        {

            foreach (AbstractComponent ac in sl)

            {

                ac.Render();

            }

        }

 

        public void Add(AbstractComponent ac)

        {

            sl.Add(ac);

        }

 

        public void Remove(AbstractComponent ac)

        {

            sl.Remove(ac);

        }

}

客户端示意代码:

    /// <summary>

    /// 客户端

    /// </summary>

    class Client

    {

        static void Main(string[] args)

        {

            Composite c = new Composite();

            c.Add(new SampleComponent());

            //渲染复杂构件

            c.Render();

        }

}

 

 

总结:

组合模式解耦了客户程序与复杂元素内部元素内部结构。

 

 

 

 

最后我们讨论下装饰者模式(decoration)

 

“装饰”二字在生活中经常听到。装饰房子简称装潢。女人最喜欢的一件事就是“装饰”(化妆)。装饰者模式就是给已有的对象增加新功能,但不是去修改原来的代码,就是借助于装饰者对象。它的魅力体现在对象A装饰成对象B还可以装饰成对象C…,可以以此装饰下去,这样被装饰的对象就拥有了所有装饰者对象的能力。还有个比较灵活的地方就是装饰对象可以任意组合装饰被装饰对象。

装饰者模式结构图:

 

设计到的角色:

抽象构件:装饰对象与被装饰对象统一接口。

具体构件:被装饰的对象。

抽象装饰者角色:包含抽象构件,实现统一接口。

具体装饰者角色:为具体构件提供新的职责。

 

示意性代码:

抽象构件:

    /// <summary>

    /// 抽象构件

    /// </summary>

    public abstract class Component

    {

        public abstract void  Operation();

}

 

具体构件:

    /// <summary>

    /// 具体构件 需要被装饰的对象

    /// </summary>

    public class ConcreteComponent:Component

    {

        public override void Operation()

        {

            //operate code

            Console.WriteLine("ConcreteComponent!");

        }

 }

 

抽象装饰者:

    /// <summary>

    /// 装饰者接口,继承自抽象构件,并包含抽象构件引用

    /// </summary>

    public class Decorator:Component

    {

        private Component component;

 

        public Decorator(Component component)

        {

            this.component = component;

        }

 

        public override void Operation() { component.Operation(); }

 }

 

具体装饰者:

    /// <summary>

    /// 具体装饰者 实现装饰者统一接口,并加入新的职责

    /// </summary>

    public class Decorator1:Decorator

    {

        public Decorator1(Component component) : base(component) { }

 

        public override void Operation()

        {

            base.Operation();

            AddNewBehavior();

        }

 

        private void AddNewBehavior()

        {

            Console.WriteLine("Decorator1");

        }

}

 

客户端代码:

class Client

    {

        static void Main(string[] args)

        {

            ConcreteComponent cc = new ConcreteComponent();

            Decorator d = new Decorator1(cc);

            d.Operation();

 

            Console.ReadLine();

        }

 }

 

 

总结:

装饰模式与继承都是为了增加对象的功能,但是装饰者模式比继承更灵活,尽量用组合代替继承。

posted on 2012-08-24 10:52  Gates.Li  阅读(1421)  评论(0编辑  收藏  举报

导航