2.外观模式

2.外观模式


2.1 基础知识

学习难度:1

使用频率:5

总分:10

定义

外观模式(Facade Pattern)为子系统中的一组接口提供一个一致的界面。此模式定义了一个高层接口,使得这一子系统更加容易使用。

说人话

提供统一接口隐藏复杂子系统细节,简化客户端与复杂子系统间的交互。其实就是封装了一下复杂的方法。

结构图

实现步骤

  • 多个子系统类:分别包含实现不同的复杂逻辑的方法。
  • 外观类:定义多个子系统对象并在构造函数初始化,定义封装子系统类复杂逻辑的方法。方法中按需调用子系统类中的方法。
  • 客户端:实例化外观对象,调用封装好的子系统类复杂逻辑方法。

说明

其实就是封装了一层,封装是面向对象很重要的特点。所以外观模式又简单又常用。


2.2 模版代码

子系统类

// 子系统类1
class Subsystem1
{
    public void Method1()
    {
        Console.WriteLine("子系统1执行方法1");
    }
}

// 子系统类2
class Subsystem2
{
    public void Method2()
    {
        Console.WriteLine("子系统2执行方法2");
    }
}

外观类

// 外观类
class Facade
{
    private Subsystem1 subsystem1;
    private Subsystem2 subsystem2;

    public Facade()
    {
        subsystem1 = new Subsystem1();
        subsystem2 = new Subsystem2();
    }

    public void Operation1()
    {
        Console.WriteLine("外观 先执行子系统1的方法 再执行子系统2的方法");
        subsystem1.Method1();
        subsystem2.Method2();
    }
    
    public void Operation2()
    {
        Console.WriteLine("外观 先执行子系统2的方法 再执行子系统1的方法");
        subsystem2.Method2();
        subsystem1.Method1();
    }
}

客户端

class Program
{
    static void Main()
    {
        Facade facade = new Facade();
        
        facade.Operation1();
        // 外观 先执行子系统1的方法 再执行子系统2的方法
        // 子系统1执行方法1
        // 子系统2执行方法2

        facade.Operation2();
        // 外观 先执行子系统2的方法 再执行子系统1的方法
        // 子系统2执行方法2
        // 子系统1执行方法1

    }
}

2.3 CSharp实践

实践需求

使用外观模式模拟巴萨和皇马进行足球比赛,需要有裁判,球员,比分计分器。

足球比赛子系统类

// 子系统1: 裁判
class Referee
{
    public void StartGame()
    {
        Console.WriteLine("裁判吹哨示意比赛开始!");
    }

    public void Goal()
    {
        Console.WriteLine("裁判宣布进球有效!");
    }
    
    public void EndGame()
    {
        Console.WriteLine("裁判吹哨示意比赛结束!");
    }
}

// 子系统2: 球员
class Player
{
    public string team;
    private string name;

    public Player(string team,string name)
    {
        this.team = team;
        this.name = name;
    }

    public void Run()
    {
        Console.WriteLine($"{name}开始跑动");
    }

    public void Shoot()
    {
        Console.WriteLine($"{name}射门了");
    }
    
    public void Goal()
    {
        Console.WriteLine($"{name}进球了");
    }
    
    public void NoGoal()
    {
        Console.WriteLine($"{name}的射门没有进球");
    }
}

// 子系统3: 比分计分器
class Scoreboard
{
    private string teamAName;
    private string teamBName;
    private int teamAScore;
    private int teamBScore;

    public Scoreboard(string teamAName,string teamBName)
    {
        this.teamAName = teamAName;
        this.teamBName = teamBName;
        this.teamAScore = 0;
        this.teamBScore = 0;
    }

    public void TeamAScores()
    {
        teamAScore++;
    }

    public void TeamBScores()
    {
        teamBScore++;
    }

    public void DisplayScore()
    {
        Console.WriteLine($"比分: {teamAName}:{teamAScore} - {teamBName}:{teamBScore}");
    }
}

足球比赛外观类

// 外观类: 足球比赛
class SoccerMatchFacade
{
    private Referee referee;
    private Player Messi;
    private Player Ronaldo;
    private Scoreboard scoreboard;

    public SoccerMatchFacade()
    {
        referee = new Referee();
        Messi = new Player("Barcelona", "Messi");
        Ronaldo = new Player("RealMadrid", "Ronaldo");
        scoreboard = new Scoreboard(Messi.team,Ronaldo.team);
    }

    public void StartGame()
    {
        Console.WriteLine("比赛准备开始...");
        referee.StartGame();
        Messi.Run();
        Ronaldo.Run();
        Console.WriteLine("比赛正式开始!");

        // 模拟比赛进行,随机射门或进球
        var random = new Random();
        for (int i = 0; i < 10; i++) // 模拟5次比赛事件
        {
            Thread.Sleep(1000); // 等待1秒钟
            int playerShootId = random.Next(2); // 哪个球员进行射门 0梅西 1C罗
            Player player = playerShootId == 0 ? Messi : Ronaldo;
            player.Shoot();

            Thread.Sleep(1000); // 等待1秒钟
            int eventOutcome = random.Next(100); // 射门结果 70以下射门失败 70以上进球
            if (eventOutcome >= 70)
            {
                player.Goal();
                if (player == Messi)
                {
                    scoreboard.TeamAScores();
                }
                else
                {
                    scoreboard.TeamBScores();
                }
            }
            else
            {
                player.NoGoal();
            }

            scoreboard.DisplayScore(); // 显示比分
        }

        EndGame();
    }

    private void EndGame()
    {
        referee.EndGame();
        scoreboard.DisplayScore(); // 显示比分
        Console.WriteLine("比赛结束,所有球员回家!");
    }
}

客户端

class Program
{
    static void Main()
    {
        SoccerMatchFacade soccerMatchFacade = new SoccerMatchFacade();
        
        soccerMatchFacade.StartGame();
    }
}

2.4 Unity实践

实践需求

使用外观模式,创建暗夜猎手薇恩对象并打印属性。

创建英雄和打印英雄属性类

public class CreatHeroGameObject
{
    public GameObject Creat(GameObject gameObject)
    {
            return GameObject.Instantiate(gameObject, Vector3.zero, Quaternion.identity);
    }
}

public class ShowHeroAttribute
{
    public void Show(GameObject gameObject)
    {
        Debug.Log($"英雄名字是{gameObject.name} ");
    }
}

英雄外观类

public class HeroFacade
{
    private CreatHeroGameObject creatHeroGameObject;
    private ShowHeroAttribute showHeroAttribute;
    
    public HeroFacade()
    {
        creatHeroGameObject = new CreatHeroGameObject();
        showHeroAttribute = new ShowHeroAttribute();
    }

    public void CreateHeroAndShowAttribute(GameObject gameObject)
    {
        var go = creatHeroGameObject.Creat(gameObject);
        showHeroAttribute.Show(go);
    }
}

客户端

public class TestFacadePattern : MonoBehaviour
{
    public GameObject vayne;

    void Start()
    {
        HeroFacade heroFacade = new HeroFacade();
        if (vayne != null)
        {
            heroFacade.CreateHeroAndShowAttribute(vayne);
        }
    }
}

运行结果



转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏