C#设计模式

前言

大家熟知的GOF23种设计模式,源自《Design Patterns: Elements of Reusable Object-Oriented Software》一书,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 合著,四人组Gang of Four简称GOF!总结了在面 向对象语言开发过程中常见问题的解决方案! 设计模式是面向对象语言开发过程中,遇到的种种场景和问题,然后提出的思 路和解决方案,最后沉淀下来,就成了设计模式--- 有具体招数可循; 设计模式其实就是解决问题的思路,是前辈总结出来的有效方式方法,就是套 路! 学习设计模式,就是为了站在前辈的肩膀上,能更快捷优雅的解决面向对 象程序开发设计问题。

设计模式分类

三大类

  1. 创建型设计模式
    1. 关注对象的创建
  1. 行为型设计模式
    1. 关注类与类之间的关系
  1. 结构型设计模式
    1. 关注对象和行为的分离

套路

设计模式六大原则与23种设计模式的关系 设计模式是解决问题的具体套路,降龙十八掌 六大原则是程序设计的指导原则,道家的小无相功, 没有具体招数,没有具体的标准。

类和类之间的关系

单个类没有任何意义!面向对象决定了类和类之间的各种关系!

横向:平级关系

  1. 组合关系 :

组合也是关联关系的一种特例,它体现的是一 种contains-a的关系,这种关系比聚合更强,也称为强聚合。 例如:人与心脏

  1. 聚合关系(Aggregation):

表示的是整体和部分的关系, 整体与部分是可以分开(has-a)。

例如:车和发动机

  1. 关联关系(Association):

两个类之间语义级别的一种强依 赖关系。

例如:班级与学生、球员与球队

  1. 依赖关系(Dependence):

假设A类的变化引起了B类的变 化,则说名B类依赖于A类。---方法里面/参数,是一种很淡 的关联---单向的依赖

纵向:层级关系

  1. 继承
    1. 强继承:任何子类继承父类,都必须拥有父类的一切行为 和属性
  1. 实现
    1. 强实现:子类实现接口,必须实现接口的方法

关系:非常紧密

类和类的强弱关系

继承≈实现 >组合>聚合>关联>依赖

结构型设计模式常规套路:组合优于继承!

结构型设计模式

7种结构型设计模式,关注类与类之间的关系 其实就是折腾组合与继承,(组合优于继承) 为程序提供更好的灵活性和扩展性。

Adapter Pattern(适配器)

将一个接口转换成客户希望的另一个接口,使接口不兼容的 那些类可以一起工作,其别名为包装器(Wrapper)。

场景:

现在很多操作几乎是重复的调用API和自己封装好API,例如数据库操作,都是CRUD操作,但是如果要进行优化,是用了第三方库的时候,方法名字是和自己封装的名字是对应不上的,但是也想要使用,所以需要适配器类才能让他和目前的方法进行适配。

现存已有的方法:

public interface IHelper
{
    void Add<T>();
    void Delete<T>();
    void Update<T>();
    void Query<T>();
}

需要适配的方法:

 public class RedisHelper
 {
     /// <summary>
     /// 第三方提供的sdk
     /// </summary>
     public RedisHelper()
     {
         Console.WriteLine("构造RedisHelper");
     }
     public void AddRedis<T>()
     {
         Console.WriteLine($"This is {this.GetType().Name} AddRedis");
     }

     public void DeleteRedis<T>()
     {
         Console.WriteLine($"This is {this.GetType().Name} DeleteRedis");
     }

     public void QueryRedis<T>()
     {
         Console.WriteLine($"This is {this.GetType().Name} QueryRedis");
     }

     public void UpdateRedis<T>()
     {
         Console.WriteLine($"This is {this.GetType().Name} UpdateRedis");
     }
 }

类适配器

原理:继承第三方库和现有的方法接口,然后可以实现接口,调用第三方库的方法

缺点:由于继承了第三方类库,就导致拥有了第三方类库的方法,这样的话不安全,具有一定的侵入性

public class RedisClassAdapter : RedisHelper, IHelper
{
    public void Add<T>()
    {
        base.AddRedis<T>();
    }

    public void Delete<T>()
    {
        base.DeleteRedis<T>();
    }

    public void Query<T>()
    {
        base.QueryRedis<T>();
    }

    public void Update<T>()
    {
        base.UpdateRedis<T>();
    }
}

使用方法:

IHelper helper = new RedisClassAdapter();
helper.Add<Program>();
helper.Delete<Program>();
helper.Update<Program>();
helper.Query<Program>();

对象适配器

原理:在类中,写一个需要适配的类的实例化,然后实现接口,调用实例化中的方法。

建议使用对象适配器,能够防止方法泄露,而且可以复用,根据构造函数进行传值可以多种类一起使用。

/// <summary>
/// Redis 对象适配器
/// </summary>
public class RedisObjectAdapter : IHelper
{
    private readonly RedisHelper redisHelper = new RedisHelper();

    //public RedisObjectAdapter(RedisHelper _redisHelper)
    //{
    //    redisHelper = _redisHelper;
    //}

    public void Add<T>()
    {
        redisHelper.AddRedis<T>();
    }

    public void Delete<T>()
    {
        redisHelper.DeleteRedis<T>();
    }

    public void Query<T>()
    {
        redisHelper.QueryRedis<T>();
    }

    public void Update<T>()
    {
        redisHelper.UpdateRedis<T>();
    }
}

总结:

适合做重构和接入新的东西。

对象适配器 > 类适配器

Bridge(桥接)

Composite(组合)

Decorator(装饰)

原理:组合+继承~~ 完成层层装饰~~

代码:

基础抽象类:

public abstract class AbstractStudent// : Object
{
    public int Id { get; set; }
    public string Name { get; set; }

    public abstract void Study();
}

继承抽象类代码:

 public class StudentVip : AbstractStudent
 {
     /// <summary>
     /// 付费  上课前要预习   
     /// 上课学习
     /// </summary>
     public override void Study()
     {
         Console.WriteLine("{0} is a vip student studying .net Vip", Name);
     }
 }

装饰器类:继承基础抽象类,证明这个装饰类也是学生类

 public abstract class AbstractDecorator : AbstractStudent// 装饰后还是一个学生
 {
     private AbstractStudent _Student = null;
     public AbstractDecorator(AbstractStudent student) : base()
     {
         _Student = student;
     }
     public override void Study()
     {
         //Console.WriteLine("***********************");
         _Student.Study();
         //Console.WriteLine("***********************");
     }
 }

装饰器若干:

可以写多种修饰器代码,然后执行父类的Study方法之后写入自己的修饰。

public class StudentDecoratorVideo : AbstractDecorator
{
    public StudentDecoratorVideo(AbstractStudent student) : base(student)
    {
    }
    public override void Study()
    {
        base.Study();
        Console.WriteLine("获取视频代码。。。");
    }
}

若干:。。。。。。。。。。

使用代码:

AbstractStudent student = new StudentVip()
{
    Id = 123,
    Name = "小海"
};

// 装饰的顺序不一样 执行也不一样
// 多个装饰 随意修饰
student = new StudentDecoratorVideo(student);
student = new StudentDecoratorAnswer(student);
student = new StudentDecoratorHomework(student);

student.Study();

效果:

Facade(外观/门面)

Flyweight(享元)

Proxy(代理)

给某一个对象提供一个代理对象,并由代理对象控制对原对 象的引用。

例如:

  • 地产代理
  • 火车票代售点
  • 翻墙梯子
  • VPN

代码:

业务接口:

public interface ISubject
{
    /// <summary>
    /// get
    /// </summary>
    /// <returns></returns>
    bool GetSomething();

    /// <summary>
    /// do
    /// </summary>
    void DoSomething();
}

现有的原本类的方法:

public class RealSubject : ISubject
{
    public RealSubject()
    {
        Thread.Sleep(2000);
        long lResult = 0;
        for (int i = 0; i < 100000000; i++)
        {
            lResult += i;
        }
        Console.WriteLine("RealSubject被构造。。。");
    }

    /// <summary>
    /// 火车站查询火车票
    /// </summary>
    public bool GetSomething()
    {
        Console.WriteLine("坐车去火车站看看余票信息。。。");
        Thread.Sleep(3000);
        Console.WriteLine("到火车站,看到是有票的");
        return true;
    }

    /// <summary>
    /// 火车站买票
    /// </summary>
    public void DoSomething()
    {
        //Console.WriteLine("This is DoSomething Before");
        //try
        //{


        Console.WriteLine("开始排队。。。");
        Thread.Sleep(2000);
        Console.WriteLine("终于买到票了。。。");
        //}
        //catch (Exception)
        //{

        //    throw;
        //}
    }
}

代理模式,将现有的类包一层代码:需要使用一个缓存类库

public class ProxySubject : ISubject
{
    /// <summary>
    /// RealSubject只实例化一次,单例代理
    /// </summary>
    private static ISubject _iSubject = new RealSubject();

    /// <summary>
    /// 缓存代理--提升性能
    /// 查询票
    /// </summary>
    /// <returns></returns>
    public bool GetSomething()
    {
        //bool bResult = _iSubject.GetSomething(); 
        //return bResult;
        
        string key = $"{nameof(ProxySubject)}_{nameof(GetSomething)}";
        bool bResult = false;
        if (CustomCache.Exist(key))
        {
            bResult = CustomCache.Get<bool>(key);
        }
        else
        {
            bResult = _iSubject.GetSomething();
            CustomCache.Add(key, bResult);
        }

        return bResult;
        return _iSubject.GetSomething();
    }


    /// <summary>
    /// 日志--异常处理--只要通过Proxy来调用 就能获得这两个功能
    /// 买票
    /// </summary>
    public void DoSomething()
    {
        try
        {
            Console.WriteLine("This is DoSomething Before");
            _iSubject.DoSomething();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            throw;
        }
    }
}

缓存类库:用来判断这个代理有没有加入

public class CustomCache
{
    private static Dictionary<string, object> CustomCacheDictionary = new Dictionary<string, object>
        ();
    public static void Add(string key, object value)
    {
        CustomCacheDictionary.Add(key, value);
    }
    public static T Get<T>(string key)
    {
        return (T)CustomCacheDictionary[key];
    }
    public static bool Exist(string key)
    {
        return CustomCacheDictionary.ContainsKey(key);
    }
}

总结:

使用情况:

可以增加一些公共的业务逻辑,而不修改历史代码,可以在原来的逻辑之前或者之后进行增加新的业务。

结构型设计模式:

通过新的类来进行包装; 包一层大法; 没有任何问题是包一层不能解决的,如果不能解决,再包一层;

行为型设计模式

11种行为型设计模式,是最大 的一个家族了。 行为型设计模式关注的是对象和 行为的分离,直白点说就是行为(方 法)是放在这个类里面,还是那个类 里面,关注的内容更细腻,因此套 路也更多!

核心:做行为的转移,做甩锅。

Interpreter(解释器)

Template Method(模板方法)

Chain of Responsibility(责任链)

使多个对象都有处理请求的机会,从而避免了请求的发送者和接收 者之间的耦合关系,将这些对象串成一条链,并沿着这条链一直传 递该请求,直到有对象处理它为止。 行为型设计模式的巅峰之作,无止境的行为封装转移!

场景模拟:

请假-审批流程

Context上下文环节,行为型设计模式的标配

因为行为型模式是关注对象和行为的分离 也就是把方法转移来转移去 那些参数信息和中间结果就得存一下 这就是Context了

审批业务逻辑转移 :

上下文保存变量类:

public class ApplyContext
{
    public int Id { get; set; }
    public string Name { get; set; }
    /// <summary>
    /// 请假时长
    /// </summary>
    public int Hour { get; set; }
    public string Description { get; set; }
    public bool AuditResult { get; set; }
    public string AuditRemark { get; set; }
}

基础业务逻辑:

很明显的问题:面向过程编程,完全没有封装。。

Console.WriteLine("找项目经理审批");
if (context.Hour <= 8)
{
    Console.WriteLine("PM审批通过");
}
Console.WriteLine("找主管审批");
if (context.Hour <= 16)
{
    Console.WriteLine("主管审批通过");
}
else
{
    //..... 继续往后去找人审批
    Console.WriteLine("************************************");
}
封装-继承-多态

把每层封装为一个类:相同的写一个基类里面

public abstract class AbstractAuditor
{
    public int Id { get; set; }
    public string Name { get; set; }

    // 因为必须有此方法 所以必须是抽象方法abstract修饰 
    public abstract void Audit(ApplyContext context);

    /// <summary>
    /// 下一个审批者
    /// </summary>
    protected AbstractAuditor _NextAuditor;

    /// <summary>
    /// 用作设置下一个审批者
    /// </summary>
    /// <param name="nextAuditor">下一个审批者</param>
    public void SetNextAuditor(AbstractAuditor nextAuditor)
    {
        _NextAuditor = nextAuditor;
    }
}

PM类:

 public class PM : AbstractAuditor
 {

     public override void Audit(ApplyContext context)
     {
         if (context.Hour <= 8)
         {
             context.AuditResult = true;
             context.AuditRemark = "PM审批通过";
         }
         else
         {
             _NextAuditor.Audit(context);   //把新一个要审批的行为转移走了;
         }
     }
 }

..........省略一百层。。。。

使用:

设置每一层的人员,并且在上层自己设置下一级是哪个人。

AbstractAuditor pM = new PM()
{
    Id = 123,
    Name = "其乐无穷"
};
AbstractAuditor charge = new Charge()   //请假者自己去找主管审批
{
    Id = 234,
    Name = "诺"
};
AbstractAuditor manager = new Manager()
{
    Id = 345,
    Name = "麦子熟了"
};
pM.SetNextAuditor(charge);
charge.SetNextAuditor(manager);

 设置完下一层的时候 执行下审批
pM.Audit(context);
从POP到OOP的升级
从菜鸟走向中级开发

使用场景:

如果一个流程有很多个环节,业务由其中一个或者多个协作处理, 就可以选择责任链模式!

  1. 流程审批
  2. 工资结算
  3. 管道处理模型

总结:

甩锅大法~~ 为了保证自己的稳定; 在这个类中不去固定某一个 类型,而是让别人来执行;

Command(命令)

Iterator(迭代器)

Mediator(中介者)

Memento(备忘录)

Observer(观察者)

业务背景:

一只神奇的猫

猫叫一声之后触发 一系列的行为:

1、小孩儿哭了

2、兄弟醒了

3、狗叫了

4、爸爸生气了~·

5、邻....

要求:以面向对象的想来模拟当前的这个场景:

代码:

基础代码:

很明显,Miao的时候确实都触发了,但是职责太多,猫应该只做自己的事情,其他的动作甩给上层处理

public void Miao()
{
    Console.WriteLine("{0} Miao.....", this.GetType().Name);
    new Mouse().Run();//猫和老鼠是啥关系--依赖
    new Chicken().Woo();
    new Baby().Cry();
    new Brother().Turn();
    new Dog().Wang();
    new Father().Roar();
    new Mother().Whisper();
    new Neighbor().Awake();
    new Stealer().Hide();
}
修改为观察者模式OOP:
public List<IObserver> observerlist = new List<IObserver>();
public void MiaoObserver()
{
    Console.WriteLine("{0} MiaoObserver.....", this.GetType().Name);
    foreach (var observer in observerlist) //具体执行的是什么玩意, 猫不关注;  集合中有什么行为,就执行什么行为;
    {
        observer.Action();
    }
}

IObserver接口:

/// <summary>
/// 只是为了把多个对象产生关系,方便保存和调用
/// 方法本身其实没用
/// </summary>
public interface IObserver
{
    void Action();
}

使用:

已经把刚才的Miao给拆开,而且做到了任务单一,把一些任务甩给调用层,上一层

Cat cat = new Cat(); 
cat.observerlist.Add(new Baby());
cat.observerlist.Add(new Brother());
cat.observerlist.Add(new Chicken());
cat.observerlist.Add(new Dog());
cat.observerlist.Add(new Father());
cat.observerlist.Add(new Mother());
cat.MiaoObserver(); 
修改为委托实现:
public Action ActionHander;
public void MiaoDelegate()
{
    Console.WriteLine("{0} MiaoDelegate.....", this.GetType().Name);
    ActionHander?.Invoke();
}

委托使用:

Cat cat = new Cat();
cat.ActionHander += new Baby().Action;
cat.ActionHander += new Brother().Action;
cat.ActionHander += new Chicken().Action;
cat.ActionHander += new Dog().Action; 
cat.ActionHander += new Father().Action;
cat.ActionHander += new Mother().Action;
cat.ActionHander += new Cat().MiaoDelegate;
//cat.ActionHander.Invoke(); //可以直接执行委托

cat.MiaoDelegate();
注意:

本质OOP和委托没有区别

OOP: 把一堆的对象保存起来

委托:把方法包装到委托中去了------委托的本质:其实是一个类;

修改为事件:
public event Action ActionHanderEvent;
public void MiaoEventHander()
{
    Console.WriteLine("{0} MiaoEventHander.....", this.GetType().Name);
    ActionHanderEvent?.Invoke();
}

事件使用:

Cat cat = new Cat();
cat.ActionHanderEvent += new Baby().Action;
cat.ActionHanderEvent += new Brother().Turn;
cat.ActionHanderEvent += new Chicken().Woo;
cat.ActionHanderEvent += new Dog().Wang;
cat.ActionHanderEvent += new Father().Roar;
cat.ActionHanderEvent += new Mother().Whisper;
cat.ActionHanderEvent += new Cat().MiaoDelegate;
//cat.ActionHanderEvent.Invoke();  //不允许的

//cat.MiaoEventHander();
委托和事件的区别:

事件---执行的执行,只允许在当前定义时间的这个类里面执行,不允许在外面执行,就是子类都不能执行;

搭建框架的时候,需要一些权限的管控; WPF 控件 Winform 控件里面;+= 方法的时候,都是事件,而不是委托;

State(状态)

Strategy(策略)

Visitor(访问者)

创建型设计模式

6种创建型设计模式,关注对象的创建, 其实就是如何new一个对象的问题, 这里也是有非常多的套路

Singleton(单例)

介绍:

就是整个程序有且仅有一个实例。该类负责创建自己的对象, 同时确保只有一个对象被创建。 自己创建自己,保证在进程中只有这个一个对象; 结构最简单的设计模式,没有之一。

单例:双判断+锁

业务背景:

有些时候重复New对象导致重置对象或者说浪费内存,则需要单例模式,但是由于多线程的时候

代码:
public class SingletonBase<T> where T : class, new()
{
    private static T _Instance;

    private static object ObjLock = new object();

    /// <summary>
    /// 双判断+锁
    /// </summary>
    /// <returns></returns>
    public static T CreateInstanc()
    {
        if (_Instance == null)
        {
            // 由于考虑到多线程的线程安全问题 所以使用加锁 方式处理
            lock (ObjLock)
            {
                if (_Instance == null)
                {
                    _Instance = new T();
                }
            }
        }
        return _Instance;
    }
}

静态构造函数 单例:

静态构造函数:特点

在整个进程中,执行且只执行一次的;

所以在静态函数中返回单例。

代码:

private SingletonSeoncd()
{
    long lResult = 0;
    for (int i = 0; i < 10000000; i++)
    {
        lResult += i;
    }
    Thread.Sleep(2000);
    Console.WriteLine($"{GetType().Name}被构造一次 {Thread.CurrentThread.ManagedThreadId}");
}

/// <summary>
/// 静态构造函数:特点 
///     在整个进程中,执行且只执行一次的;
/// </summary>
static SingletonSeoncd()
{
    _SingletonSeoncd = new SingletonSeoncd();
}

public static SingletonSeoncd CreateInstance()
{
    return _SingletonSeoncd;
}

// 静态类属性 返回
private static SingletonSeoncd _SingletonSeoncd;

public int Id { get; set; }
public string Name { get; set; }

public static void Show()
{
    Console.WriteLine(" Show 方法~~");
}

初始化的时候声明静态变量 单例:

public static SingletonThird CreateInstance()
{
    return _SingletonThird;
}

private static SingletonThird _SingletonThird = new SingletonThird();

应用场景:

线程池、数据库连接池、配置文件对象、IOC容器实例 等需要单例的

New个对象不费什么事儿 请不要画蛇添足,没有必须单例的,请勿单例!

总结:

  1. 私有化构造函数
  2. 对外提供获取实例的方法
  3. 提供静态变量,实例重用

Factory Method(工厂方法)

介绍:

通过定义工厂父类负责定义创建对象的公共接口, 而子类则负责生成具体的对象。 每一个不同的的对象分别自定义个工厂+抽象;

Abstract Factory(抽象工厂)

介绍:

在抽象工厂模式中,接口是负责创建一个相关对象的工厂。 每个生成的工厂都能按照工厂模式提供对象。 工厂+约束!

Builder(建造者)

介绍:

是将一个复杂的对象的构建与它的表示分离, 使得同样的构建过程可以创建不同的表示, 创建者模式隐藏了复杂对象的创建过程。

核心: 就是灵活应用;

有之前的审批流程代码:

由于也需要修改代码进行改变组织架构,所以引进建造者模式,进行灵活使用

代码:

IBuilder接口:

/// <summary>
/// 建造者;可能需要创建很多对象,然后要组装;
/// </summary>
public interface IBuilder
{

    public AbstractAuditor CreateCharge();

    public AbstractAuditor CreateManager();

    //建造者:最终要建造一个审批的开始节点; 
    public AbstractAuditor Build();
}

每一个新的建造者:

public class AuditorWorkFlowsBuild : IBuilder
{
    public AbstractAuditor Build()
    {
        AbstractAuditor pm = new PM();
        AbstractAuditor charge = CreateCharge();
        AbstractAuditor manager = CreateManager();
        pm.SetNextAuditor(charge);
        charge.SetNextAuditor(manager);
        return pm;
    }

    public AbstractAuditor CreateCharge()
    {
        return new Charge();
    }

    public AbstractAuditor CreateManager()
    {
        return new Manager();
    }
}

使用:

说明:

可以写多个建造者,所以在切换组织的时候,建造者切换即可。

//如果组织架构发生变化;
//审批历程发生改变;  可以直接换掉建造者;
IBuilder builder = new AuditorWorkFlowsBuild();
AbstractAuditor pm = builder.Build();
 pm.Audit(context);

Prototype(原型)

介绍:

是用于创建重复的对象,同时又能保证性能。专门用来批量生产对象!

原理:

既要快速获得对象实例 又要对象直接不能互相干扰

copy大法:

MemberwiseClone

代码:

在创建实例的时候,不用返回上一个实例,直接复制一个即可,这样既能保证实例是最新的,也能保证快。

 public static SingletonPrototype CreateInstance()
 {
     //MemberwiseClone: 内存拷贝;  不是浅拷贝
     object oInstance = _SingletonPrototype.MemberwiseClone();
     return (SingletonPrototype)oInstance;
 }


 private static SingletonPrototype _SingletonPrototype = new SingletonPrototype();

创建对象的方式:

  1. new()
  2. 克隆
  3. 反序列化
  4. 反射

Simple Factory(简单工厂)

介绍:

是通过专门定义一个类来负责创建其他类的实例, 被创建的实例通常都具有共同的父类。

业务背景:

继续请假审批流程:

由于使用建造者的时候,修改建造者也比较繁琐,所以进一步优化,改为配置文件即可。

代码:

/// <summary>
/// 这个工厂是为了来创建建造者的
/// </summary>
public class SimpBuidlerFactory
{
    // 建造者的dll库
    private static string dllName = "XH.DesignPattern.ResponsibilityChainPattern.dll";
    // 建造者的类名:可以包装为配置文件 修改配置文件即可
    private static string typeName = "XH.DesignPattern.ResponsibilityChainPattern.Builder.AuditorWorkFlowsBuild";

    public static IBuilder CreateBuilderInstance()
    {
        //字符串:  写到配置文件中去;
        //          修改配置文件的信息,不用重新编译,可以直接生效 
        //return new AuditorWorkFlowsNewBuild(); 
        //反射
        Assembly assembly = Assembly.LoadFrom(dllName); // 获取DLL 
        Type type = assembly.GetType(typeName);// 获取DLL中的当前文件类型
        object oinstance = Activator.CreateInstance(type);// 创建对象
        return oinstance as IBuilder;
    }
}

使用:

IBuilder builder = SimpBuidlerFactory.CreateBuilderInstance(); 
AbstractAuditor pm = builder.Build();

pm.Audit(context);

总结:

结果: 如果组织架构发生改变; 只需要实现新的建造者,然后修改配置文件即可,根本就不用去修改历史代码;

这才是设计模式的正确使用方式;

设计模式总结:

结构型:包一层

行为型:甩锅大法

创建型:灵活运用

设计模式真的应该分3大类,创建型-结构型-行为型,就三类 招数

所以,23种设计模式,大家不要着相,不用去背, 其实学会三个核心套路,见招拆招,有问题不要想着先用什 么设计模式,先看看要做到什么,然后用什么核心套路,然 后根据特点微调,设计模式应该是自然而然 设计模式不是完美的,是为了解决一类问题而存在,通常在 解决一类问题时,还会带来其他问题,设计者要做的就是扬 长避短,比如设计模式融合,比如其他技术手段,最终解决 问题---程序设计,其实就是走一步看一步,不是一蹴而就

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值