GOF设计模式

简介

GoF是设计模式的经典名著Design Patterns: Elements of Reusable Object-Oriented Software(中译本名为《设计模式——可复用面向对象软件的基础》)的四位作者,他们分为是:Elich Gamma、Richard Helm、Ralph Johnson、以及John Vlissides。这四个人常被称为Gang of Four, 即四人组,简称GoF。
为解决某一类普遍存在的问题而提供的一种解决方案
设计模式不是万能的,只有合理利用设计模式才能写出合理的代码

划分

根据目的划分

根据模式是用来完成什么工作来划分,这种方式可分为创建型模式、结构型模式和行为型模式 3 种。
创建型模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。GoF 中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。
结构型模式:用于描述如何将类或对象按某种布局组成更大的结构,GoF 中提供了代理、适配器、桥接、装饰、外观、享元、组合等 7 种结构型模式。
行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。GoF 中提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器等 11 种行为型模式。

根据作用范围来分

根据模式主要用于类上还是对象上,这种方式可分为类模式、对象模式
类模式:用于处理类与子类之间的关系,这些关系通过继承来建立,是静态的,在编译时刻便确定下来了。GoF中的工厂方法、(类)适配器、模板方法、解释器属于该模式。
对象模式:用于处理对象之间的关系,这些关系可以通过组合或聚合来实现,在运行时刻是可以变化的,更具动态性。GoF 中除了以上 4 种,其他的都是对象模式。

范围\目的创建型模式结构型模式行为型模式
类模式工厂方法(类)适配器模板方法、解释器
对象模式单例代理策略
(对象)适配器命令
原型桥接职责链
装饰状态
抽象工厂外观观察者
享元中介者
建造者迭代器
组合访问者
备忘录

设计模式解析

工厂方法模式

基本介绍

简单工厂模式就是创建一个工厂类,由这个类来封装实例化对象的行为,根据传入的参数类型来创建具体的产品对象,并返回产品对象的实例

优点

工厂方法模式的优势在于完全符合了开闭原则,在新增产品时不需要再改动已存在的代码,使工厂类和产品类的代码完全解耦,更利于程序的扩展

缺点

当新增产品时,需要同时新增产品类和工厂类,导致系统中的类是成对增加,增加了系统的复杂度

适用场景

主要适用于调用者不知道应该创建哪个具体的对象,只能根据传入的条件返回相应对象的场景
工厂类是不知道要创建哪个产品对象的,只能根据用户提供的条件才能知道需要哪个产品对象
简单工厂模式的好处在于将对象的创建过程和使用过程进行解耦,减少新增具体产品时修改代码的复杂度

演示代码

//提供一个创建对象实例的功能,而无需关系其具体实现,被创建实例的类型可以是接口、抽象类,也可以是具体的类.
    class Program
    {
        static void Main(string[] args)
        {
            Food food1 = FoodFactory.CreatFood("土豆");
            food1.Cook();
            Food food2 = FoodFactory.CreatFood("鸡蛋");
            food2.Cook();

            Console.ReadKey();
        }
    }


    public abstract class Food
    {
        public abstract void Cook();
    }

    public class Tomato : Food
    {
        public override void Cook()
        {
            Console.WriteLine("土豆");
        }
    }

    public class Eggs : Food
    {
        public override void Cook()
        {
            Console.WriteLine("鸡蛋");
        }
    }


    /// <summary>
    /// 简单工厂
    /// </summary>
    public class FoodFactory
    {
        public static Food CreatFood(string type)
        {
            Food food = null;
            if (type.Equals("土豆"))
            {
                food = new Tomato();
            }
            if (type.Equals("鸡蛋"))
            {
                food = new Eggs();
            }
            return food;
        }
    }

抽象工厂模式

基本介绍

抽象工厂模式是将具有一定共性的产品封装到一块,由工厂类分别为这些产品提供创建对象的方法,调用者可以根据不同的需求调用工厂类的具体方法来获得产品实例

优点

将具有一定共性的产品集合封装到一起,在实际开发中更符合具体的业务场景

  • 隔离产品代码 : 在应用层隔离具体产品的代码 , 客户端无须关心产品创建的细节 ;
  • 创建产品族 : 将一个系列的产品族 , 统一到一起创建 ;

缺点

降低了系统的扩展性,当新增产品时需要修改工厂类,在工厂类的基类和实现类中都需要增加对应的方法。比如说,用户也想订购VR眼镜来玩游戏。那么工厂基类中需要增加创建VR眼镜的方法,所有的工厂实现类中都需要增加对该方法的实现,系统扩展性比较差

  • 扩展困难 : 规定了所有可能被创建的产品集合 , 产品族中扩展新的产品困难 , 需要修改抽象工厂的接口 ;
  • 增加难度 : 增加了系统的抽象性和理解难度 ;

适用场景

  1. 忽略创建细节 : 客户端不关心产品实例如何被创建 , 实现等细节 ;
  2. 创建产品族 : 强调一系列相关的产品对象 , 一般是同一个产品族 , 一起使用创建对象需要大量重复的代码 ;
  3. 产品类库 : 提供一个产品类的库 , 所有的产品以同样的接口出现 , 使客户端不依赖于具体实现 ;

使用抽象工厂模式 , 可以在工厂变化时 , 不需要修改客户端使用工厂的代码

演示代码

//提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
class Program
{
    static void Main(string[] args)
    {
        //获取图形抽象工厂
        AbstractFactory shapeFactory = FactoryProducer.getFactory(Option.SHAPE);
        //获取图形抽象类
        shape shape1 = shapeFactory.getShape(ShapeType.Triangle);
        //图形类方法
        shape1.draw();
        
        shape shape2 = shapeFactory.getShape(ShapeType.Circle);
        shape2.draw();
        
        //获取颜色抽象工厂
        AbstractFactory colorFactory = FactoryProducer.getFactory(Option.COLOR);
        //获取颜色抽象类
        Color color1 = colorFactory.getColor(ColorType.Red);
        //颜色类方法
        color1.fill();
        
        Color color2 = colorFactory.getColor(ColorType.Green);
        color2.fill();
        Console.ReadKey();
    }
}

public interface shape
{
    void draw();
}

public class Rectangle : shape
{
    public void draw()
    {
        Console.WriteLine("矩形实现形状的接口方法draw()。");
    }
}

public class Square : shape
{
    public void draw()
    {
        Console.WriteLine("正方形实现形状的接口方法draw()。");
    }
}

public class Circle : shape
{
    public void draw()
    {
        Console.WriteLine("圆形实现形状的接口方法draw()。");
    }
}

public class Triangle : shape
{
    public void draw()
    {
        Console.WriteLine("三角形实现形状的接口方法draw()。");
    }
}

public enum ShapeType
{
    Rectangle,
    Square,
    Circle,
    Triangle
}

public enum ColorType
{
    Red,
    Yellow,
    Green
}

public interface Color
{
    void fill();
}

public class Red : Color
{
    public void fill()
    {
        Console.WriteLine("给形状填充红色!");
    }
}

public class Yellow : Color
{
    public void fill()
    {
        Console.WriteLine("给形状填充黄色!");
    }
}

public class Green : Color
{
    public void fill()
    {
        Console.WriteLine("给形状填充绿色!");
    }
}

public abstract class AbstractFactory
{
    public abstract shape getShape(ShapeType s);
    public abstract Color getColor(ColorType c);
}

public class ShapeFactory : AbstractFactory
{
    public override Color getColor(ColorType c)
    {
        return null;
    }

    public override shape getShape(ShapeType shapetype)
    {
        if (shapetype == ShapeType.Circle)
        {
            return new Circle();
        }
        else if (shapetype == ShapeType.Rectangle)
        {
            return new Rectangle();
        }
        else if (shapetype == ShapeType.Triangle)
        {
            return new Triangle();
        }
        else
        {
            return new Square();
        }
    }
}

public class ColorFactory : AbstractFactory
{
    public override Color getColor(ColorType colortype)
    {
        if (colortype == ColorType.Green)
        {
            return new Green();
        }
        else if (colortype == ColorType.Red)
        {
            return new Red();
        }
        else
        {
            return new Yellow();
        }
    }

    public override shape getShape(ShapeType s)
    {
        return null;
    }
}

public enum Option
{
    SHAPE,
    COLOR
}

public class FactoryProducer
{
    public static AbstractFactory getFactory(Option t)
    {
        if (t == Option.COLOR)
        {
            return new ColorFactory();
        }
        else
        {
            return new ShapeFactory();
        }
    }
}

观察者模式

基本介绍

定义了对象之间一对多的依赖 , 令多个观察者对象同时监听某一个主题对象 , 当主题对象 发生改变时 , 所有的观察者都会收到通知并更新 ;
观察者有多个 , 被观察的主题对象只有一个

优点

抽象耦合:在观察者和被观察者之间 , 建立了一个抽象的耦合;
由于耦合是抽象的 , 可以很容易扩展观察者和被观察者;
广播通信:观察者模式支持广播通信 , 类似于消息广播 , 如果需要接收消息 , 只需要注册一下即可;

缺点

依赖过多:观察者之间细节依赖过多,会增加时间消耗和程序的复杂程度;
这里的细节依赖指的是触发机制,触发链条;如果观察者设置过多,每次触发都要花很长时间去处理通知;
循环调用:避免循环调用,观察者与被观察者之间绝对不允许循环依赖,否则会触发二者之间的循环调用,导致系统崩溃;

适用场景

如用户关注某个商品的价格,降价时进行通知,这样用户和商品产生了关联,触发机制就是商品降价

演示代码

//定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。                                      ——《设计模式》GoF
    class Program
    {
        static void Main(string[] args)
        {
            //我们有了三位储户,都是武林高手,也比较有钱
            Depositor huangFeiHong = new BeiJingDepositor("黄飞鸿", 3000);
            Depositor fangShiYu = new BeiJingDepositor("方世玉", 1300);
            Depositor hongXiGuan = new BeiJingDepositor("洪熙官", 2500);

            BankMessageSystem beijingBank = new BeiJingBankMessageSystem();
            //这三位开始订阅银行短信业务
            beijingBank.Add(huangFeiHong);
            beijingBank.Add(fangShiYu);
            beijingBank.Add(hongXiGuan);

            //黄飞鸿取100块钱
            huangFeiHong.GetMoney(100);
            beijingBank.Notify();

            //黄飞鸿和方世玉都取了钱
            huangFeiHong.GetMoney(200);
            fangShiYu.GetMoney(200);
            beijingBank.Notify();

            //他们三个都取了钱
            huangFeiHong.GetMoney(320);
            fangShiYu.GetMoney(4330);
            hongXiGuan.GetMoney(332);
            beijingBank.Notify();

            Console.Read();
        }
    }

    public abstract class BankMessageSystem
    {
        protected IList<Depositor> observers;

        //构造函数初始化观察者列表实例
        protected BankMessageSystem()
        {
            observers = new List<Depositor>();
        }

        //增加预约储户
        public abstract void Add(Depositor depositor);

        //删除预约储户
        public abstract void Delete(Depositor depositor);

        //通知储户
        public void Notify()
        {
            foreach (Depositor depositor in observers)
            {
                if (depositor.AccountIsChanged)
                {
                    depositor.Update(depositor.Balance, depositor.OperationDateTime);
                    //账户发生了变化,并且通知了,储户的账户就认为没有变化
                    depositor.AccountIsChanged = false;
                }
            }
        }
    }

    //北京银行短信系统,是被观察者--该类型相当于具体主体角色ConcreteSubject
    public sealed class BeiJingBankMessageSystem : BankMessageSystem
    {
        //增加预约储户
        public override void Add(Depositor depositor)
        {
            //应该先判断该用户是否存在,存在不操作,不存在则增加到储户列表中,这里简化了
            observers.Add(depositor);
        }

        //删除预约储户
        public override void Delete(Depositor depositor)
        {
            //应该先判断该用户是否存在,存在则删除,不存在无操作,这里简化了
            observers.Remove(depositor);
        }
    }

    //储户的抽象接口--相当于抽象观察者角色(Observer)
    public abstract class Depositor
    {
        //状态数据
        private string _name;
        private int _balance;
        private int _total;
        private bool _isChanged;

        //初始化状态数据
        protected Depositor(string name, int total)
        {
            this._name = name;
            this._balance = total;//存款总额等于余额
            this._isChanged = false;//账户未发生变化
        }

        //储户的名称,假设可以唯一区别的
        public string Name
        {
            get { return _name; }
            private set { this._name = value; }
        }

        public int Balance
        {
            get { return this._balance; }
        }

        //取钱
        public void GetMoney(int num)
        {
            if (num <= this._balance && num > 0)
            {
                this._balance = this._balance - num;
                this._isChanged = true;
                OperationDateTime = DateTime.Now;
            }
        }

        //账户操作时间
        public DateTime OperationDateTime { get; set; }

        //账户是否发生变化
        public bool AccountIsChanged
        {
            get { return this._isChanged; }
            set { this._isChanged = value; }
        }

        //更新储户状态
        public abstract void Update(int currentBalance, DateTime dateTime);
    }

    //北京的具体储户--相当于具体观察者角色ConcreteObserver
    public sealed class BeiJingDepositor : Depositor
    {
        public BeiJingDepositor(string name, int total) : base(name, total) { }

        public override void Update(int currentBalance, DateTime dateTime)
        {
            Console.WriteLine(Name + ":账户发生了变化,变化时间是" + dateTime.ToString() + ",当前余额是" + currentBalance.ToString());
        }
    }

桥接模式

基本介绍

将对象的行为抽象为接口,作为抽象类的成员属性在抽象层进行组合
桥接模式是比较常用的设计模式之一,在创建型模式、结构型模式和行为型模式分类中,桥接模式归属于结构型模式
桥接模式可以将一个大类或者一系列紧密相关的类拆分成 控制层实现层 两个相互独立的层次结构,从而能在开发时分别使用

优点

桥接模式最大的优点在于将一个具有多重功能的系统进行解耦,拆分成相互独立的层次,从而提高系统的可扩展性
桥接模式符合开闭原则,不管新增控制层或实现层的代码都可以很容易实现,而且它们不会相互影响
也符合单一原则,控制层专注于控制层的逻辑处理,实现层专注于实现层的逻辑处理
业务系统在调用时只与控制层交互,不用关心实现层的具体逻辑

缺点

桥接模式的主要缺点是增加了系统的设计与理解难度,并且,想要从一个多重功能中识别到相互独立的层次结构也不是一件容易的事情

适用场景

桥接模式的主要特点是将一个具有多重功能的系统拆分成两个相互独立的层次结构。所以,在识别到一个类具有两个相互独立变化的维度时,可以优先考虑使用该模式
桥接模式也常用于解决由于继承造成的代码侵入问题,在不希望或者不适用于继承的场景下也可以考虑使用该模式
如果想拆分一个复杂庞大的类时,也可以考虑使用该模式,前提是这个类可以拆分成多个相互独立的层次结构
桥接模式在处理跨平台应用、 支持多种类型的数据库服务器或与多个特定种类 (例如云平台和社交网络等) 的 API 供应商协作时会特别有用
当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时。
当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。

演示代码

//将抽象部分与实现部分分离,使它们都可以独立地变化。
class Program
{
    static void Main(string[] args)
    {
        TankPlatform tankPlatform = new PCTankPlatform();
        T50 t50 = new T50(tankPlatform);
        t50.Run();
        t50.Shot();
        Console.ReadKey();
    }
}

//细节抽象类
public abstract class Tank
{
    //组合抽象类,桥接变化的平台
    private TankPlatform tankPlatform;
    /// <summary>
    /// _tankPlatform
    /// </summary>
    public TankPlatform _tankPlatform
    {
        get
        {
            return tankPlatform;
        }
        set
        {
            tankPlatform = value;
          
        }
    }
    public abstract void Shot();
    public abstract void Run();
}

//平台抽象类
public abstract class TankPlatform
{     
    public abstract void DrawTank();
    public abstract void DoShot();
}

public class PCTankPlatform : TankPlatform
{
    public override void DoShot()
    {
        Console.WriteLine("pc平台坦克开火");
    }

    public override void DrawTank()
    {
        Console.WriteLine("pc平台坦克运行");
    }
}

public class T50 : Tank
{
    public T50(TankPlatform tankPlatform)
    {
        _tankPlatform = tankPlatform;
    }
    public override void Run()
    {
        _tankPlatform.DrawTank();
    }

    public override void Shot()
    {
        _tankPlatform.DoShot();
    }
}

外观模式

基本介绍

外观模式也叫门面模式,在创建型模式、结构型模式和行为型模式分类中,外观模式归属于结构型模式
在我们实际的工作中,外观模式是最常用的一种设计模式之一
比如,我们把几个方法中共用的逻辑抽象成一个独立的方法,那么这个方法就可以理解成外观模式
外观模式是通过引入一个外观角色来简化调用者与各个子系统之间的交互,为复杂的子系统调用提供一个统一的入口,降低子系统与调用者的耦合度,使得扩展更加方便
外观模式实现步骤:

  1. 抽象各个子系统的业务逻辑
  2. 将抽象过的业务逻辑封装到门面类中
  3. 调用者使用门面类中的方法完成自己的逻辑

优点

外观模式给各个子系统提供统一的入口,调用者使用起来很简单
外观模式把各个子系统和调用者解耦,扩展性会更好。比如,想要增加一个子系统时,只需要按照外观模式的规范进行开发,调用者和外观类都不用修改

缺点

如果设计不合理,增加新的子系统时可能需要修改外观类或调用者的源代码,违背了“开闭原则”

适用场景

  1. 需要为一个复杂的子系统提供一系列逻辑支持的时候,可以考虑使用外观模式

中台系统需要给业务系统提供多个方法支持,可以用外观模式

  1. 当调用者需要调用多个子系统来完成自己的逻辑时,可以考虑使用外观模式

比如日志处理框架 SLF4J,它对调用者提供接口。logback、log4j等各种日志框架作为子系统去实现这些接口
业务系统需要记录日志时,调用SLF4J门面类即可,而不必关心具体使用的是哪一个框架

演示代码

// 为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。      ——《设计模式》GoF
        static void Main(string[] args)
        {
            SystemFacade facade = new SystemFacade();
            facade.Buy();
            Console.ReadKey();
        }
        // 身份认证子系统A
        public class AuthoriationSystemA
        {
            public void MethodA()
            {
                Console.WriteLine("执行身份认证");
            }
        }

        // 系统安全子系统B
        public class SecuritySystemB
        {
            public void MethodB()
            {
                Console.WriteLine("执行系统安全检查");
            }
        }

        // 网银安全子系统C
        public class NetBankSystemC
        {
            public void MethodC()
            {
                Console.WriteLine("执行网银安全检测");
            }
        }

        //更高层的Facade
        public class SystemFacade
        {
            private AuthoriationSystemA auth;
            private SecuritySystemB security;
            private NetBankSystemC netbank;

            public SystemFacade()
            {
                auth = new AuthoriationSystemA();
                security = new SecuritySystemB();
                netbank = new NetBankSystemC();
            }

            public void Buy()
            {
                auth.MethodA();//身份认证子系统
                security.MethodB();//系统安全子系统
                netbank.MethodC();//网银安全子系统

                Console.WriteLine("我已经成功购买了!");
            }
        }
    }

GoF的23种设计模式总览

前面说明了 GoF 的 23 种设计模式的分类,现在对各个模式的功能进行介绍。

分类及定义

名称功能使用频率
单例(Singleton)模式某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。★★★★☆
原型(Prototype)模式将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。★★★☆☆
工厂方法(Factory Method)模式定义一个用于创建产品的接口,由子类决定生产什么产品。★★★★★
抽象工厂(AbstractFactory)模式提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。★★★★★
建造者(Builder)模式将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。★★☆☆☆
代理(Proxy)模式为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。★★★★☆
适配器(Adapter)模式将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。★★★★☆
桥接(Bridge)模式将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。★★★☆☆
装饰(Decorator)模式动态的给对象增加一些职责,即增加其额外的功能。★★★☆☆
外观(Facade)模式为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。★★★★★
享元(Flyweight)模式运用共享技术来有效地支持大量细粒度对象的复用。★☆☆☆☆
组合(Composite)模式将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。★★★★☆
模板方法(TemplateMethod)模式定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。★★★☆☆
策略(Strategy)模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。★★★★☆
命令(Command)模式将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。★★★★☆
职责链(Chain of Responsibility)模式把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。★★★☆☆
状态(State)模式允许一个对象在其内部状态发生改变时改变其行为能力。★★★☆☆
观察者(Observer)模式多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。★★★★★
中介者(Mediator)模式定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。★★☆☆☆
迭代器(Iterator)模式提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。★★★★★
访问者(Visitor)模式在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。★☆☆☆☆
备忘录(Memento)模式在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。★★☆☆☆
解释器(Interpreter)模式提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。★☆☆☆☆

使用频率排序

创建型模式(5)
工厂方法模式:★★★★★
抽象工厂模式:★★★★★
单例模式:★★★★☆
简单工厂模式:★★★★☆            // 不属于 gof-23
原型模式:★★★☆☆
生成器模式:★★☆☆☆
结构型模式(7)
外观模式:★★★★★
代理模式:★★★★☆
组合模式:★★★★☆
适配器模式:★★★★☆
桥接模式:★★★☆☆
装饰模式:★★★☆☆
享元模式:★☆☆☆☆
行为型模式(11)
迭代器模式:★★★★★
观察者模式:★★★★★
命令模式:★★★★☆
策略模式:★★★★☆
模板方法模式:★★★☆☆
责任链模式:★★★☆☆
状态模式:★★★☆☆
备忘录模式:★★☆☆☆
中介者模式:★★☆☆☆
解释器模式:★☆☆☆☆
访问者模式:★☆☆☆☆

总结图片

引用

https://www.cnblogs.com/chenpi/category/780173.html
https://blog.csdn.net/as576228266?type=blog
https://www.yuque.com/kshare/2020/353292e1-daf5-496a-9f1f-609d2a46f54d
https://blog.csdn.net/guyuweilove/article/details/117507343
https://blog.csdn.net/Wenhao_China/article/details/124019926

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
本书设计实例从面向对象的设计中精选出23个设计模式,总结了面向对象设计中最有价值的经验,并且用简洁可复用的形式表达出来。本书分类描述了一组设计良好,表达清楚的软件设计模式,这些模式在实用环境下有特别有用。 前 言 本书并不是一本介绍面向对象技术或设计的书,目前已有不少好书介绍面向对象技术或设计。本书假设你至少已经比较熟悉一种面向对象编程语言,并且有一定的面向对象设计经验。当我们提及“类型”和“多态”,或“接口”继承与“实现”继承的关系时,你应该对这些概念了然于胸,而不必迫不及待地翻阅手头的字典。 另外,这也不是一篇高级专题技术论文,而是一本关于设计模式的书,它描述了在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案。设计模式捕获了随时间进化与发展的问题的求解方法,因此它们并不是人们从一开始就采用的设计方案。它们反映了不为人知的重新设计和重新编码的成果,而这些都来自软件开发者为了设计出灵活可复用的软件而长时间进行的艰苦努力。设计模式捕获了这些解决方案,并用简洁易用的方式表达出来。 设计模式并不要求使用独特的语言特性,也不采用那些足以使你的朋友或老板大吃一惊的神奇的编程技巧。所有的模式均可以用标准的面向对象语言实现,这也许有时会比特殊的解法多费一些功夫,但是为了增加软件的灵活性和可复用性,多做些工作是值得的。 一旦你理解了设计模式并且有了一种“Aha!”(而不是“Huh?”)的应用经验和体验后,你将用一种非同寻常的方式思考面向对象设计。你将拥有一种深刻的洞察力,以帮助你设计出更加灵活的、模块化的、可复用的和易理解的软件—这也是你为何着迷于面向对象技术的源动力,不是吗? 当然还有一些提示和鼓励:第一次阅读此书时你可能不会完全理解它,但不必着急,我们在起初编写这本书时也没有完全理解它们!请记住,这不是一本读完一遍就可以束之高阁的书。我们希望你在软件设计过程中反复参阅此书,以获取设计灵感。 序 言 所有结构良好的面向对象软件体系结构中都包含了许多模式。实际上,当我评估一个面向对象系统的质量时,所使用的方法之一就是要判断系统的设计者是否强调了对象之间的公共协同关系。在系统开发阶段强调这种机制的优势在于,它能使所生成的系统体系结构更加精巧、简洁和易于理解,其程度远远超过了未使用模式的体系结构。 模式在构造复杂系统时的重要性早已在其他领域中被认可。特别地,Christopher Alexander和他的同事们可能最先将模式语言(pattern language)应用于城市建筑领域,他的思想和其他人的贡献已经根植于面向对象软件界。简而言之,软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。 在本书中,Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides介绍了设计模式的原理,并且对这些设计模式进行了分类描述。因此,该书做出了两个重要的贡献:首先,它展示了模式在建造复杂系统过程中所处的角色;其次,它为如何引用一组精心设计的模式提供了一个实用方法,以帮助实际开发者针对特定应用问题使用适当的模式进行设计。 目 录 序言 前言 读者指南 第1章 引言 1 1.1 什么是设计模式 2 1.2 Smalltalk MVC中的设计模式 3 1.3 描述设计模式 4 1.4 设计模式的编目 5 1.5 组织编目 7 1.6 设计模式怎样解决设计问题 8 1.6.1 寻找合适的对象 8 1.6.2 决定对象的粒度 9 1.6.3 指定对象接口 9 1.6.4 描述对象的实现 10 1.6.5 运用复用机制 13 1.6.6 关联运行时刻和编译时刻的 结构 15 1.6.7 设计应支持变化 16 1.7 怎样选择设计模式 19 1.8 怎样使用设计模式 20 第2章 实例研究:设计一个文档编 辑器 22 2.1 设计问题 23 2.2 文档结构 23 2.2.1 递归组合 24 2.2.2 图元 25 2.2.3 组合模式 27 2.3 格式化 27 2.3.1 封装格式化算法 27 2.3.2 Compositor和Composition 27 2.3.3 策略模式 29 2.4 修饰用户界面 29 2.4.1 透明围栏 29 2.4.2 Monoglyph 30 2.4.3 Decorator 模式 32 2.5 支持多种视感标准 32 2.5.1 对象创建的抽象 32 2.5.2 工厂类和产品类 33 2.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值