模板方法情势实施葡京国际娱乐下载

http://blog.csdn.net/womendeaiwoming/article/details/44243571

在实质上编制程序中,会不时遇到四个类中的有个别方法达成逻辑类似的场馆,那时我们可以将那几个类中的相同部分虚幻到父类中,对于有差别的地方,子类遵照本身的实际要求来分别达成。

OS中的崩溃类型

以羽毛球活动为例,打球必有发接发环节,发球分正手和反手二种(那里不钻探羽毛球类技巧术细节),一般男子单打反手发球,女子单打正手发球,但发接发那个环节的流水生产线是同样的。

      
在那边询问一下XCode用来代表种种崩溃类型的术语,补充部分这方面包车型地铁各知识。崩溃平时是指操作系统向正在运营的顺序发送的信号,所以我们在查看崩溃日志时,平常看到如下错误摘要:Application
received signal SIGSEGV。一般的话,常见的垮台类型有以下三种:

葡京国际娱乐下载 1

 

 

1、        EXC_BAD_ACCESS

abstract class Badminton
{
    public abstract void Serve();

    public abstract void Catch();

    public abstract void Play();
}

class MenSingle : Badminton
{
    public override void Serve()
    {
        Console.WriteLine("反手发球......");
    }

    public override void Catch()
    {
        Console.WriteLine("正手推底线");
    }

    public override void Play()
    {
        Serve();
        Catch();
    }
}


class WomenSingle : Badminton
{
    public override void Serve()
    {
        Console.WriteLine("正手发球.......");
    }

    public override void Catch()
    {
        Console.WriteLine("软压一拍");
    }

    public override void Play()
    {
        Serve();
        Catch();
    }
}

   
   在拜访多个早就释放的靶子或向它发送新闻时,EXC_BAD_ACCESS就会油但是生。造成EXC_BAD_ACCESS最广泛的缘由是,在初阶化方法中起初化变量时用错了全部权修饰符,那会促成对象太早地被保释。举个例子,在viewDidLoad方法中为UIViewController创设了2个包涵元素的NSArray,却将该数组的全数权修饰符设成了assign而不是strong。以往在view威尔Appear中,若要访问已经出狱掉的对象时,就会收获名为EXC_BAD_ACCESS的崩溃。

 

      
这几个崩溃产生时,查看崩溃日志,却往往得不到有用的栈消息。幸而,有1个办法用来化解这么些标题:NSZombieEnabled。

次第支付中有个主要的规格:Don't repeat yourself。而地方一段代码中,子类MenSingleWomenSingle中的Play措施是再一次的,羽球运动除男子双打、女子单打外还有男单,女子单打,混双,如此则代码中至少五处重复,那显然不便利日后保卫安全。
接下去对代码举行革新:

      
这是三个环境变量,用来调节与内部存款和储蓄器相关的标题,跟踪对象的获释过程。启用了NSZombieEnabled的话,它会用一个僵尸完毕来去你的暗中同意的dealloc完毕,也正是在引用计数降到0时,该僵尸实现会将该目的转换到僵尸对象。僵尸对象的功用是在你向它发送音信时,它会议及展览示一段日志并自动跳入调节和测试器。

abstract class Badminton
{
    protected abstract void Serve();

    protected abstract void Catch();

    public void Play()
    {
        Serve();
        Catch();
    }
}

class MenSingle : Badminton
{
    protected override void Serve()
    {
        Console.WriteLine("反手发球......");
    }

    protected override void Catch()
    {
        Console.WriteLine("正手推底线");
    }

}


class WomenSingle : Badminton
{
    protected override void Serve()
    {
        Console.WriteLine("正手发球.......");
    }

    protected override void Catch()
    {
        Console.WriteLine("软压一拍");
    }

}

      
所以,当在行使中启用NSZombie而不是让使用直接崩溃时,一个荒谬的内部存款和储蓄器访问就会化为一条不能够辨识的新闻发送给僵尸对象。僵尸对象会显示接收到的消息,然后跳入调试器,那样您就能够查阅毕竟哪时出了难点。

 

      
可以在Xcode的scheme页面中安装NSZombieEnabled环境变量。点击Product-àEdit
Scheme打开该页面,然后勾选Enable Zombie Objects复选框,如图所示:

那段代码将Play情势放到父类中落到实处,对于有出入的ServeCatch则交有子类达成,这边是模板方法格局,封装不变部分,扩张可变部分。当中Play方法称之为模板方法,ServeCatch号称基本方法。
通常模板方法(能够有三个)在父类中达成并调用基本方法以成功一定的逻辑,且不容许子类重写。
主干方式貌似为架空方法,由子类来完毕具体的贯彻。基本格局的造访修饰符平日是protected,不需求对外边展露(迪米特法则),客户端只须要调用模板方法即可。

 

这便是说,问题来了,世界羽毛球联合会没有鲜明男子双打必须用反手发球,女子单打必须正手发球。假若男双想用正手发球咋做?为适应那种具有三种大概的风貌,大家对代码稍作调整:

 葡京国际娱乐下载 2

abstract class Badminton
{
    private  void ForehandServe()
    {
        Console.WriteLine("正手发球.......");
    }

    private void BackhandServe()
    {
        Console.WriteLine("反手发球......");
    }

    protected abstract void Catch();

    protected abstract bool IsForeHandServe { get; }

    public void Play()
    {
        if (IsForeHandServe)
        {
            ForehandServe();
        }
        else
        {
            BackhandServe();
        }
        Catch();
    }
}

class MenSingle : Badminton
{
    protected override bool IsForeHandServe => false;

    protected override void Catch()
    {
        Console.WriteLine("正手推底线");
    }
}


class WomenSingle : Badminton
{
    protected override bool IsForeHandServe => true;

    protected override void Catch()
    {
        Console.WriteLine("软压一拍");
    }
}

      
僵尸在RAC出现此前功效十分大。但自从有了ALX570C,假诺你在对象的全部权方面可比在意,那么一般不会碰着内部存款和储蓄器相关的崩溃。

 

 

此处,大家经过在子类中落实属性IsForehandServe来决定父类中具体调用ForehandServe主意依旧调用BackhandServe方法。属性IsForehandServe称为钩子函数,根据钩子函数的例外达成,模板方法能够有区别的执行结果,即子类对父类发生了影响。

2、        SIGSEGV

以上,是二个模板方法的虚构使用处境。模板方法情势有个很主要的特点:父类控制流程,子类负责具体细节的落实。那里有没有联想到IoC(控制反转)?IoC的落到实处际情形势有二种,DI只是在那之中之一,模板方法格局也足以。

   
   段错误消息(SIGSEGV)是操作系统发生的二个更严重的难点。当硬件出现谬误、访问不可读的内部存储器地址或向受有限辅助的内存地址写入数据时,就会发出那些荒唐。

无数框架(如:ASP.NET
MVC)也是其一套路,框架定义一套流程,然后由不一样的类负责分化效率的实现,并留下扩张点让开发职员可依据实际需求进行扩张开发,但任何框架的处理流程开发人士是控制不了的。

   
   硬件错误这一情景并不普遍。当要读取保存在RAM中的数据,而该职位的RAM硬件有标题时,你会收取SIGSEGV。SIGSEGV越多是出新在后三种状态。私下认可情况下,代码页不容许开始展览写操作,而数据而区别意进行实施操作。当使用中的有个别指针指向代码页并计算修改指向地方的值时,你会收下SIGSEGV。当要读取2个指南针的值,而它被初步化成指向无效内存地址的垃圾值时,你也会接收SIGSEGV。

小结

模板方法格局有以下优点:
壹 、封装不变部分,扩展可变部分;

写程序就因该是那样,不仅仅是在模板方法格局中

② 、提取公共部分福利日后爱抚;

Ctrl + C,Ctrl + V 大法好,但滥用也是可怜的

三 、父类控制流程,子类负责兑现;

那般,子类便可通过扩展的不二法门来扩充效果;
并且,对于某个参差不齐的算法,大家得以明天父类的模版方法中定义好流程,然后再在子类中去完结,思路上也会清楚不少;

   
   SIGSEGV错误调试起来更困难,而招致SIGSEGV的最广大原因是不得法的类型转换。要幸免过度使用指针或尝试手动修改指针来读取私有数据结构。假如您那么做了,而在修改指针时并未理会内部存款和储蓄器对齐和填充难题,就会收到SIGSEGV。

结语

最终,附一段使用模板方法方式写的分页查询代码:

public class DbBase
{
    public virtual string TableName
    {
        get
        {
            throw new NotImplementedException($"属性:{nameof(TableName)}不得为空!");
        }
    }

    protected virtual string ConnectionString
    {
        get
        {
            throw new NotImplementedException("属性:" + nameof(ConnectionString) + "不得为空!");
        }
    }

    protected SqlConnection CreateSqlConnection()
    {
        return CreateSqlConnection(ConnectionString);
    }

    protected SqlConnection CreateSqlConnection(string connnectionString)
    {
        SqlConnection dbConnection = new SqlConnection(connnectionString);
        if (dbConnection.State == ConnectionState.Closed)
        {
            dbConnection.Open();
        }
        return dbConnection;
    }

 

public interface IPagingQuery<T>
    where T : class
{
    /// <summary>
    /// 数据总量
    /// </summary>
    int DataCount { get; }

    /// <summary>
    /// 分页查询
    /// </summary>
    /// <param name="pageNumber">页码</param>
    /// <param name="pageSize">每页数据量</param>
    /// <returns></returns>
    IEnumerable<T> PagingQuery(int pageNumber, int pageSize);
}

public abstract class PagingQueryDalBase<T> : DbBase, IPagingQuery<T>
    where T : class
{
    public int DataCount => GetDataCount();

    /// <summary>
    /// 查询数据总数SQL
    /// </summary>
    protected abstract string QueryDataCountSql();

    private int GetDataCount()
    {
        int dataCount;
        using (SqlConnection sqlConnection = base.CreateSqlConnection())
        {
            string sql = QueryDataCountSql();
            dataCount = sqlConnection.QueryFirstOrDefault<int>(sql);
        }
        return dataCount;
    }

    /// <summary>
    /// 分页查询SQL
    /// </summary>
    protected abstract string PagingQuerySql(int pageNumber, int pageSize);

    public IEnumerable<T> PagingQuery(int pageNumber, int pageSize)
    {
        if (pageNumber - 1 < 0)
        {
            throw new ArgumentException("参数:pageNumber不得小于1");
        }

        if (pageSize <= 0)
        {
            throw new ArgumentException("参数:pageNumber必须大于0");
        }
        IEnumerable<T> result;
        using (SqlConnection sqlConnection = CreateSqlConnection())
        {
            string sql = PagingQuerySql(pageNumber, pageSize);
            result = sqlConnection.Query<T>(sql);
        }
        return result;
    }
}

 

 

版权注明

本文为作者原创,版权归笔者雪飞鸿具备。
转载必须保留小说的完整性,且在页面明显地点处标明初稿链接

如有毛病, 请发送邮件和小编联系。

3、        SIGBUS

   
   总线错误信号(SIGBUG)代表无效内部存款和储蓄器访问,即访问的内部存款和储蓄器是叁个没用的内部存款和储蓄器地址。也正是说,那些地点指向的地方根本不是大体内存地址(它恐怕是某些硬件芯片的地方)。SIGSEGV和SIGBUS都羽球EXC_BAD_ACCESS的子类型。

 

4、        SIGTRAP

   
   SIGTRAP代表陷阱信号。它并不是一个的确的崩溃信号。它会在处理器执行trap指令发送。LLDB调节和测试器平时会处理此信号,并在钦赐的断点处截至运作。若是您接到了原委不明的SIGTRAP,先消除上次的输出,然后再次开始展览构建平常能缓解这一个标题。

 

5、        EXC_ARITHETIC

   
   当要除零时,应用会收到EXC_ASportageITHMETIC信号。那么些错误应该很简单化解。

 

6、        SIGILL

       SIGILL代表signal illegal
instruction(不合法命令信号)。当在处理器上实施违法命令时,它就会发出。执行不合规命令是指,将函数指针会给其余2个函数时,该函数指针由于某种原因是坏的,指向了一段一度刑满释放的内部存款和储蓄器或是四个数据段。有时你收到的是EXC_BAD_INSTRUCTION而不是SIGILL,就算它们是三次事,然则EXC_*一点差别也没有于此信号不借助连串布局。

 

7、        SIGABRT

       SIGAB帕杰罗T代表SIGNAL
ABO大切诺基T(中止信号)。当操作系统一发布现不安全的情形时,它亦可对那种状态进行更加多的主宰;必要的话,它能需要进程展开清理工科作。在调节和测试造成此信号的最底层错误时,并没有怎么好招。Cocos2d或UIKit等框架平时会在一定的前提条件没有满足或一些不好的动静出现时调用C函数abort(由它来发送此信号)。当SIGABENVISIONT出现时,控制台经常会输出多量的音信,说明具体哪个地方出错了。由于它是可决定的垮台,所以能够在LLDB控制台上键入bt命令打字与印刷出回溯新闻。

 

捌 、        看门狗超时

   
   那种崩溃平日相比较简单辨别,因为错误码是定位的0x8badf00d。(程序员也有有趣的另一方面,他们把它读作Ate
Bad
Food。)在iOS上,它日常出现在推行多个体协会助举行互联网调用而堵塞主线程的景况。因而,永远不要开始展览同步网络调用。