当前位置: 代码迷 >> 综合 >> C# 设计模式--合成模式(Composite)
  详细解决方案

C# 设计模式--合成模式(Composite)

热度:97   发布时间:2024-01-11 06:59:19.0

  Composite模式定义了单个对象和组合对象的类层次结构。(1)单个对象组合成复杂的组合对象,而多个组合对象又可以被组合成一个新的组合对象。其中,一个组合对象中的某些对象可能包容了其他对象。某些对象则表现单个基本对象,称为叶对象;某些对象代表一组对象,称为枝对象。叶对象可以组合成复杂的枝对象,而枝对象又可以被组合成新的枝对象,可以不断组合下去。

  Composite模式使用户对单个对象和组合对象的使用具有一致性。客户可以一致地使用组合结构和单个对象,而不用关心处理的是一个叶节点还是一个组合组件。Composite关键是一个抽象类,这个类既可以代表一个对象,也可以代表一个容器来包含一组对象。(1)那么。Composite关键两个思想:
  一、一个Composite对象既可包容Leaf对象,也可以其他包容Composite对象。
  二、一个Leaf类和一个Composite共享一个在抽象类中定义的公共接口Component。(2)

  在以下情况下考虑使用合成模式:
  (1)表示对象的部分和整体层次结构
  (2)忽略枝对象和叶对象的不同,用户同意使用组合结构的所有对象。

  结构图如下:


  合成模式的实现根据公共接口Component的区别分为两种形式,分别称为安全模式和透明模式。

  透明模式:
  公共接口Component中里面声明所有的用来管理子类对象的方法,包括Add()、Remove(),以及GetChild()方法。这样所有的叶对象和枝对象都有相同的接口,那么客户端可以将叶对象和枝对象同等对待而不用区分。

  示例代码如下:

using  System;
using  System.Collections.Generic;
using  System.Text;

namespace  Composite
{
    
/// <summary>
    
/// 透明模式
    
/// 一个Leaf类和一个Composite共享一个在抽象类中定义的公共接口
    
/// </summary>

    public interface ITransparence
    
{
        
/// <summary>
        
/// 获得学生的总成绩
        
/// </summary>
        
/// <returns>返回学生的总成绩</returns>

        int GetStudentScores();

        
/// <summary>
        
/// 获得学生的所有科目名称
        
/// </summary>
        
/// <returns>返回学生的所有科目名称</returns>

        string GetStudentSubjects();

        
/// <summary>
        
/// 增加叶节点
        
/// </summary>
        
/// <param name="transparence">接口类型对象</param>
        
/// <returns>操作是否成功</returns>

        bool Add(ITransparence transparence);

        
/// <summary>
        
/// 移除叶节点
        
/// </summary>
        
/// <param name="transparence">接口类型对象</param>
        
/// <returns>操作是否成功</returns>

        bool Remove(ITransparence transparence);

        
/// <summary>
        
/// 获得所有的子节点
        
/// </summary>
        
/// <returns></returns>

        List<ITransparence> GetChild();
    }
    

    
/// <summary>
    
/// 学生叶子节点
    
/// </summary>

    public class StudentLeaf : ITransparence
    
{
         
/// <summary>
       
/// 语文
       
/// </summary>

       private string _chinese;

       
/// <summary>
       
/// 数学
       
/// </summary>

       private string _math;

       
/// <summary>
       
/// 英语
       
/// </summary>

       private string _english;

       
/// <summary>
       
/// 语文成绩
       
/// </summary>

       private int _chineseScore;

       
/// <summary>
       
/// 数学成绩
       
/// </summary>

       private int _mathScore;

       
/// <summary>
       
/// 英语成绩
       
/// </summary>

       private int _englishScore;

       
/// <summary>
       
/// 构造函数:语文,数学,英语的中文名称和它的分数
       
/// </summary>
       
/// <param name="chinese"></param>
       
/// <param name="math"></param>
       
/// <param name="english"></param>

       public StudentLeaf(string chinese, string math, string english, int chineseScore, int mathScore, int englishScore)
       
{
           _chinese 
= chinese;
           _math 
= math;
           _english 
= english;
           _chineseScore 
= chineseScore;
           _mathScore 
= mathScore;
           _englishScore 
= englishScore;
       }


        
/// <summary>
        
/// 获得某个学生总成绩
        
/// </summary>
        
/// <returns></returns>

        public int GetStudentScores()
        
{
            
int scores = _chineseScore + _mathScore + _englishScore;
            
return scores;
        }


        
/// <summary>
        
/// 获得某个学生的所有科目名称
        
/// </summary>
        
/// <returns></returns>

        public string GetStudentSubjects()
        
{
            StringBuilder sb 
= new StringBuilder();
            sb.Append(
"语文:");
            sb.Append(_chinese);
            sb.Append(
" ");
            sb.Append(
"数学:");
            sb.Append(_math);
            sb.Append(
" ");
            sb.Append(
"英语:");
            sb.Append(_english);
            sb.Append(
" ");
            
return sb.ToString();
        }


        
/// <summary>
        
/// 增加叶节点
        
/// </summary>
        
/// <param name="transparence">接口类型对象</param>
        
/// <returns>操作是否成功</returns>

        public bool Add(ITransparence transparence)
        
{
            
//叶子节点不能使用该方法
            return false;
        }


        
/// <summary>
        
/// 移除叶节点
        
/// </summary>
        
/// <param name="transparence">接口类型对象</param>
        
/// <returns>操作是否成功</returns>

        public bool Remove(ITransparence transparence)
        
{
            
//叶子节点不能使用该方法
            return false;
        }


        
/// <summary>
        
/// 获得所有的子节点
        
/// </summary>
        
/// <returns></returns>

        public List<ITransparence> GetChild()
        
{
            
return null;
        }

    }


    
/// <summary>
    
/// 学生合成类
    
/// </summary>

    public class StudentComposite : ITransparence
    
{

        
private List<ITransparence> studentComposite = new List<ITransparence>();

        
/// <summary>
        
/// 获得某个学生总成绩
        
/// </summary>
        
/// <returns></returns>

        public int GetStudentScores()
        
{
            
int scores = 0;
            
foreach(ITransparence transparence in studentComposite)
            
{
                scores 
+= transparence.GetStudentScores();
            }

            
return scores;
        }


        
/// <summary>
        
/// 获得某个学生的所有科目名称
        
/// </summary>
        
/// <returns></returns>

        public string GetStudentSubjects()
        
{
            StringBuilder sb 
= new StringBuilder();
            
foreach (ITransparence transparence in studentComposite)
            
{
                sb.Append(transparence.GetStudentSubjects());
                sb.Append(
" ");
            }

            
return sb.ToString();
        }


        
/// <summary>
        
/// 增加叶节点
        
/// </summary>
        
/// <param name="transparence">接口类型对象</param>
        
/// <returns>操作是否成功</returns>

        public bool Add(ITransparence transparence)
        
{
            studentComposite.Add(transparence);
            
return true;
        }


        
/// <summary>
        
/// 移除叶节点
        
/// </summary>
        
/// <param name="transparence">接口类型对象</param>
        
/// <returns>操作是否成功</returns>

        public bool Remove(ITransparence transparence)
        
{
            studentComposite.Remove(transparence);
            
return true;
        }


        
/// <summary>
        
/// 获得所有的子节点
        
/// </summary>
        
/// <returns></returns>

        public List<ITransparence> GetChild()
        
{
            
return studentComposite;
        }

    }



    
/// <summary>
    
/// 客户类
    
/// </summary>

    public class Client
    
{
        
static void Main(string[] args)
        
{
            
int scores = 0;
            
string studentSubjectsName = string.Empty;

            StudentComposite sudentCompositeRoot 
= new StudentComposite();
            StudentLeaf studentLeafRootOne 
= new StudentLeaf("11","12","13",70,71,72);
            StudentLeaf studentLeafRootTwo 
= new StudentLeaf("21","22","23",80,81,82);
            StudentLeaf studentLeafRootThree
= new StudentLeaf("31","32","33",90,91,92);
            sudentCompositeRoot.Add(studentLeafRootOne);
            sudentCompositeRoot.Add(studentLeafRootTwo);
            sudentCompositeRoot.Add(studentLeafRootThree);

            StudentComposite sudentCompositeChild 
= new StudentComposite();
            StudentLeaf studentLeafChildOne 
= new StudentLeaf("41","42","43",60,61,62);
            StudentLeaf studentLeafChildTwo 
= new StudentLeaf("51","52","53",50,51,52);
            sudentCompositeChild.Add(studentLeafChildOne);
            sudentCompositeChild.Add(studentLeafChildTwo);

            sudentCompositeRoot.Add(sudentCompositeChild);

            scores 
= sudentCompositeRoot.GetStudentScores();
            Console.WriteLine(
" 总成绩:{0} ", scores);
            studentSubjectsName 
= sudentCompositeRoot.GetStudentSubjects();
            Console.WriteLine(
" 所有科目名称:{0} ", studentSubjectsName);

            StudentLeaf studentLeaf 
= new StudentLeaf("61""62""63"404142);
            scores 
= studentLeaf.GetStudentScores();
            Console.WriteLine(
" 总成绩:{0} ", scores);
            studentSubjectsName 
= studentLeaf.GetStudentSubjects();
            Console.WriteLine(
" 所有科目名称:{0} ", studentSubjectsName);          
       }

   }

}

 

  安全模式:

  公共接口Component中里面不声明所有的用来管理子类对象的方法,而将这些方法(Add()、Remove(),以及GetChild()方法)在Composite类中实现。因为叶对象不包含任何对象,所以叶对象不需要操作叶子对象的方法,故是安全的。在这种情况下,在客户端使用管理子类对象的方法,自然就出错了。

  示例代码如下:

using  System;
using  System.Collections.Generic;
using  System.Text;

namespace  Composite
{
    
/// <summary>
    
/// 安全模式
    
/// 一个Leaf类和一个Composite共享一个在抽象类中定义的公共接口
    
/// </summary>

    public interface ITransparence
    
{
        
/// <summary>
        
/// 获得学生的总成绩
        
/// </summary>
        
/// <returns>返回学生的总成绩</returns>

        int GetStudentScores();

        
/// <summary>
        
/// 获得学生的所有科目名称
        
/// </summary>
        
/// <returns>返回学生的所有科目名称</returns>

        string GetStudentSubjects();
    }
    

    
/// <summary>
    
/// 学生叶子节点
    
/// </summary>

    public class StudentLeaf : ITransparence
    
{
         
/// <summary>
       
/// 语文
       
/// </summary>

       private string _chinese;

       
/// <summary>
       
/// 数学
       
/// </summary>

       private string _math;

       
/// <summary>
       
/// 英语
       
/// </summary>

       private string _english;

       
/// <summary>
       
/// 语文成绩
       
/// </summary>

       private int _chineseScore;

       
/// <summary>
       
/// 数学成绩
       
/// </summary>

       private int _mathScore;

       
/// <summary>
       
/// 英语成绩
       
/// </summary>

       private int _englishScore;

       
/// <summary>
       
/// 构造函数:语文,数学,英语的中文名称和它的分数
       
/// </summary>
       
/// <param name="chinese"></param>
       
/// <param name="math"></param>
       
/// <param name="english"></param>

       public StudentLeaf(string chinese, string math, string english, int chineseScore, int mathScore, int englishScore)
       
{
           _chinese 
= chinese;
           _math 
= math;
           _english 
= english;
           _chineseScore 
= chineseScore;
           _mathScore 
= mathScore;
           _englishScore 
= englishScore;
       }


        
/// <summary>
        
/// 获得某个学生总成绩
        
/// </summary>
        
/// <returns></returns>

        public int GetStudentScores()
        
{
            
int scores = _chineseScore + _mathScore + _englishScore;
            
return scores;
        }


        
/// <summary>
        
/// 获得某个学生的所有科目名称
        
/// </summary>
        
/// <returns></returns>

        public string GetStudentSubjects()
        
{
            StringBuilder sb 
= new StringBuilder();
            sb.Append(
"语文:");
            sb.Append(_chinese);
            sb.Append(
" ");
            sb.Append(
"数学:");
            sb.Append(_math);
            sb.Append(
" ");
            sb.Append(
"英语:");
            sb.Append(_english);
            sb.Append(
" ");
            
return sb.ToString();
        }

    }


    
/// <summary>
    
/// 学生合成类
    
/// </summary>

    public class StudentComposite : ITransparence
    
{

        
private List<ITransparence> studentComposite = new List<ITransparence>();

        
/// <summary>
        
/// 获得某个学生总成绩
        
/// </summary>
        
/// <returns></returns>

        public int GetStudentScores()
        
{
            
int scores = 0;
            
foreach(ITransparence transparence in studentComposite)
            
{
                scores 
+= transparence.GetStudentScores();
            }

            
return scores;
        }


        
/// <summary>
        
/// 获得某个学生的所有科目名称
        
/// </summary>
        
/// <returns></returns>

        public string GetStudentSubjects()
        
{
            StringBuilder sb 
= new StringBuilder();
            
foreach (ITransparence transparence in studentComposite)
            
{
                sb.Append(transparence.GetStudentSubjects());
                sb.Append(
" ");
            }

            
return sb.ToString();
        }


        
/// <summary>
        
/// 增加叶节点
        
/// </summary>
        
/// <param name="transparence">接口类型对象</param>
        
/// <returns>操作是否成功</returns>

        public bool Add(ITransparence transparence)
        
{
            studentComposite.Add(transparence);
            
return true;
        }


        
/// <summary>
        
/// 移除叶节点
        
/// </summary>
        
/// <param name="transparence">接口类型对象</param>
        
/// <returns>操作是否成功</returns>

        public bool Remove(ITransparence transparence)
        
{
            studentComposite.Remove(transparence);
            
return true;
        }


        
/// <summary>
        
/// 获得所有的子节点
        
/// </summary>
        
/// <returns></returns>

        public List<ITransparence> GetChild()
        
{
            
return studentComposite;
        }

    }



    
/// <summary>
    
/// 客户类
    
/// </summary>

    public class Client
    
{
        
static void Main(string[] args)
        
{
            
int scores = 0;
            
string studentSubjectsName = string.Empty;

            StudentComposite sudentCompositeRoot 
= new StudentComposite();
            StudentLeaf studentLeafRootOne 
= new StudentLeaf("11","12","13",70,71,72);
            StudentLeaf studentLeafRootTwo 
= new StudentLeaf("21","22","23",80,81,82);
            StudentLeaf studentLeafRootThree
= new StudentLeaf("31","32","33",90,91,92);
            sudentCompositeRoot.Add(studentLeafRootOne);
            sudentCompositeRoot.Add(studentLeafRootTwo);
            sudentCompositeRoot.Add(studentLeafRootThree);

            StudentComposite sudentCompositeChild 
= new StudentComposite();
            StudentLeaf studentLeafChildOne 
= new StudentLeaf("41","42","43",60,61,62);
            StudentLeaf studentLeafChildTwo 
= new StudentLeaf("51","52","53",50,51,52);
            sudentCompositeChild.Add(studentLeafChildOne);
            sudentCompositeChild.Add(studentLeafChildTwo);

            sudentCompositeRoot.Add(sudentCompositeChild);

            scores 
= sudentCompositeRoot.GetStudentScores();
            Console.WriteLine(
" 总成绩:{0} ", scores);
            studentSubjectsName 
= sudentCompositeRoot.GetStudentSubjects();
            Console.WriteLine(
" 所有科目名称:{0} ", studentSubjectsName);

            StudentLeaf studentLeaf 
= new StudentLeaf("61""62""63"404142);
            scores 
= studentLeaf.GetStudentScores();
            Console.WriteLine(
" 总成绩:{0} ", scores);
            studentSubjectsName 
= studentLeaf.GetStudentSubjects();
            Console.WriteLine(
" 所有科目名称:{0} ", studentSubjectsName);          
       }

   }

}


 

参考资料:
(1)《C# 设计模式》《 Desing Patterns in C#》(美)Steven John Metsker 著, 颜炯 译。
(2)设计模式 可复用面向对象软件的基础 Design Patterns Elements of Reusable Object-Oriented Software 》(美)Erich Gamma Richard Helm Ralph Johnson John Vlissides 著,李英军 等译。

 

  相关解决方案