北川广海の梦

北川广海の梦

设计模式:生成器模式与原型模式

2021-11-09

建造者模式

当我们需要构建一个房子的时候,这是一个比较复杂的过程,因为房子由好几个部分组成:门、窗户、屋顶、墙壁。如果按照普通的做法,我们可能会写一个房子类,然后写上一个构造函数,房子有几个部分,构造函数就有几个参数。

客户端在构建房子的时候,还需要知道所有的细节,有些参数并不是必要的。这样的构造函数使用起来太麻烦了。

而通过建造者,就可以解决这个问题。

 public interface IHouseBuilder
    {
        void WithWindow(string window);
        void WithDoor(string door);
        void WithRoof(string roof);
        void WithWall(string wall);

        IHouse Build();
    }

    public interface IHouse
    {
        public string Window { get; set; }
        public string Door { get; set; }
        public string Roof { get; set; }
        public string Wall { get; set; }
    }

    public class NormalHouse : IHouse
    {
        public string Window { get; set; }
        public string Door { get; set; }
        public string Roof { get; set; }
        public string Wall { get; set; }
    }

    public class HouseBuilder : IHouseBuilder
    {
        private readonly IHouse _house;

        public HouseBuilder()
        {
            _house = new NormalHouse();
        }

        public void WithWindow(string window)
        {
            _house.Window = window;
        }

        public void WithDoor(string door)
        {
            _house.Door = door;
        }

        public void WithRoof(string roof)
        {
            _house.Roof = roof;
        }

        public void WithWall(string wall)
        {
            _house.Wall = wall;
        }

        public IHouse Build()
        {
            return _house;
        }
    }

这是一个房屋的构建器,用户只需拿到自己想要的构建器就能自由选择房子想要的部件。并且我们可以封装一些特定的构造器,减少暴露给用户的属性,例如一个石头墙的房子,它的专属构造器就不允许用户再调用WithWall方法了。

相比工厂模式,构造器模式专注于分步骤构建一个复杂对象。而工厂模式专注于构建一系列相关对象。

原型模式

通过原型模式,我们可以轻松的实现对象的复制。

public interface IPrototype<T>
    {
        T Clone();
    }

    public class Weapon : IPrototype<Weapon>
    {
        public string Code { get; set; }
        public int Damage { get; set; }

        public Weapon Clone()
        {
            return new Weapon
            {
                Code = Code + "",
                Damage = Damage
            };
        }
    }

    public class Robot : IPrototype<Robot>
    {
        public string Code { get; set; }
        public Weapon Weapon { get; set; }

        public Robot Clone()
        {
            return new Robot()
            {
                Code = Code + "",
                Weapon = Weapon.Clone()
            };
        }
    }

通过这个通用接口,客户端可以对所有实现了这个接口的类进行复制。但是在包含循环引用的时候,原型模式的处理会非常麻烦。