如何避免代码重复

本文关键字:代码 何避免 | 更新日期: 2023-09-27 18:02:58

我在HourDay两个类的Output()方法中有相同的代码。有没有办法避免在一个地方而不是两个地方修改代码?

class Program
{
    static void Main(string[] args)
    {
        Hour hour = new Hour("20150715 080000");
        Day day = new Day(hour);
        Console.WriteLine(String.Format("Hour: {0}", hour.Output()));
        Console.WriteLine(String.Format("Day: {0}", day.Output()));
    }
}
public interface IMoment
{
    string OutputMoment();
}
class Hour : IMoment
{
    public string Date;
    public string Time;
    public Hour (string s)
    {
        string[] parts = s.Split(';');
        this.Date = parts[0];
        this.Time = parts[1];
    }
    public string Output()
    {
        return Date + " " + Time;
    }
}
class Day : IMoment
{
    public string Date;
    public string Time;
    public Day(Hour hour)
    {
        this.Date = hour.Date;
        this.Time = hour.Time;
    }
    public string Output()
    {
        return Date + " " + Time;
    }
}

如何避免代码重复

不要犯创建基类来共享该方法的错误。这是对继承的一种常见的误用。这种技术通常会失效,并且将无意义的类引入到类的公共接口中。继承不能用于代码共享。用于"Liskov替换"。

相反,创建一个静态助手方法,它将这两个值作为参数并计算结果。这允许您实现一次格式化。这很容易实现,几乎总是有效,而且不会影响类的公共API。不要担心稍微大一点的语法占用空间。这不是什么大问题(大多数时候)。

作为usr回答的另一种选择,您可以重构代码,使编写数据到屏幕的关注点分开。

所以你的HourDay类没有2个责任(单一责任原则),以及使代码更容易更新与更复杂的输出功能在未来,因为你只需要改变在作家类的代码。(或抽象并创建例如FileMomentWriter等)

public interface IMoment
{ 
   string MomentType {get;}
   string Date {get;set;}
   string Time {get;set;}
}

public class Hour:IMoment
{
    public string MomentType {get{return "Hour";}}
    public string Date {get;set;}
    public string Time {get;set;}
    public Hour (string s)
    {
        string[] parts = s.Split(';');
        this.Date = parts[0];
        this.Time = parts[1];
    }
}
public class Day: IMoment
{
    public string MomentType {get{return "Day";}}
    public string Date{get;set;}
    public string Time{get;set;}
    public Day(Hour hour)
    {
        this.Date = hour.Date;
        this.Time = hour.Time;
    }
}
public class ConsoleMomentWriter
{
   public void Write(IMoment moment)
   {
      Console.WriteLine("{0}: {1} {2}",moment.MomentType,moment.Date,moment.Time);
   }
}
class Program
{
    static void Main(string[] args)
    {
        Hour hour = new Hour("20150715 080000");
        Day day = new Day(hour);
        var writer = new ConsoleMomentWriter();
        writer.Write(hour);
        writer.Write(day);
    }
}

你应该用abstract class代替interface:

class Program
{
    static void Main(string[] args)
    {
        Hour hour = new Hour("20150715;080000");
        Day day = new Day(hour);
        Console.WriteLine(String.Format("Hour: {0}", hour.OutputMoment()));
        Console.WriteLine(String.Format("Day: {0}", day.OutputMoment()));
    }
}
public abstract class Moment
{
    public string Date;
    public string Time;
    public virtual string OutputMoment()
    {
        return Date + " " + Time;
    }
    public override string ToString()
    {
        return OutputMoment();
    }
}
class Hour : Moment
{
    public Hour(string s)
    {
        string[] parts = s.Split(';');
        this.Date = parts[0];
        this.Time = parts[1];
    }
}
class Day : Moment
{
    public Day(Hour hour)
    {
        this.Date = hour.Date;
        this.Time = hour.Time;
    }
}

如果需要的话,将OutputMoment()标记为virtual还将允许您超越默认实现。我还重写了ToString()这样你就可以直接使用Console.WriteLine(hour);而不用调用OutputMoment()

直接继承一个拥有public成员的类:)

class HasOutput
{
    public string Date;
    public string Time;
    public string Output()
    {
        return Date + " " + Time;
    }
}
class Hour : HasOutput, IMoment
{
    public Hour (string s)
    {
        string[] parts = s.Split(';');
        this.Date = parts[0];
        this.Time = parts[1];
    }
}
class Day : HasOutput
{
    public Day(Hour hour)
    {
        this.Date = hour.Date;
        this.Time = hour.Time;
    }
}