工厂模式和抽象工厂模式

2020年5月7日 2082点热度 0人点赞 0条评论
内容纲要

工厂模式和抽象工厂模式,都是避免调用者直接 new 一个新的实例,预先将创建逻辑编写在工厂代码中,并且对实例进行和一些配置,然后分配调用者使用。

原有代码:

HttpRequest 作用是检查网址是否能够访问以及健康状态。

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

namespace Children
{
    class Program
    {
        static void Main(string[] args)
        {
            HttpRequest request = new HttpRequest("https://whuanle.cn");
            HttpStatusCode code = request.GetAsync().Result;
            Console.WriteLine("网站状态:" + Enum.GetName(code.GetType(), code));
            Console.ReadKey();
        }
    }

    /// 
    /// 代码加工厂
    /// 
    public class HttpRequest
    {
        private HttpClient httpClient;
        private Uri uri;
        public HttpRequest(string url)
        {
            uri = new Uri(url);
            httpClient = new HttpClient();
        }
        public async Task GetAsync()
        {
            var request = await httpClient.GetAsync(uri);
            return request.StatusCode;
        }
    }
}

这里出来新的问题:

  • 使用者调用时,要自己传递 URL,容易出错
  • 限定只能访问约定的几个网站,不能自己随便填写 URL 地址
  • ... ...

首先使用工厂方法来优化:

using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

namespace Children
{
    class Program
    {
        static void Main(string[] args)
        {
            IRequest request = Factory.Create(UrlType.Baidu);
            HttpStatusCode code = request.GetAsync().Result;
            Console.WriteLine("网站状态:" + Enum.GetName(code.GetType(), code));
            Console.ReadKey();
        }
    }

    #region 

    public interface IRequest
    {
        Task GetAsync();
    }

    public class BaiduRequest : IRequest
    {
        private HttpClient httpClient = new HttpClient();
        private Uri uri = new Uri("https://www.baidu.com");
        public async Task GetAsync()
        {
            var request = await httpClient.GetAsync(uri);
            return request.StatusCode;
        }
    }
    public class QQRequest : IRequest
    {
        private HttpClient httpClient = new HttpClient();
        private Uri uri = new Uri("https://www.qq.com");
        public async Task GetAsync()
        {
            var request = await httpClient.GetAsync(uri);
            return request.StatusCode;
        }
    }
    #endregion
    #region
    public enum UrlType
    {
        Baidu = 1,
        QQ = 2
    }
    public static class Factory
    {
        public static IRequest Create(UrlType type)
        {
            switch (type)
            {
                case UrlType.Baidu:
                    return new BaiduRequest();
                case UrlType.QQ:
                    return new QQRequest();
            }
            return default;
        }
    }
    #endregion
}

但是又出现了新的问题,就是一个网站有多个页面,要判断多个页面的情况。

假设两个网站,都只有两个页面,One,Two;

使用抽象工厂模式如下:

using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

namespace Children
{
    class Program
    {
        static void Main(string[] args)
        {
            ICreateFactory factory = FactoryFactory.Create(UrlType.BAIDU);
            IRequest request = factory.One();
            HttpStatusCode code = request.GetAsync().Result;
            Console.WriteLine("网站状态:" + Enum.GetName(code.GetType(), code));
            Console.ReadKey();
        }
    }

    #region 共同继承

    // 创建工厂模式的接口,给抽象工厂模式使用的
    public interface ICreateFactory
    {
        IRequest One();
        IRequest Two();
    }

    // 访问页面
    public interface IRequest
    {
        Task GetAsync();
    }

    #endregion

    #region 访问百度百科相应页面

    public abstract class IBaiduRequest : IRequest
    {
        protected HttpClient httpClient = new HttpClient();
        protected Uri baseUri = new Uri("https://baike.baidu.com/");
        public abstract Task GetAsync();
    }

    public class Baidu_DOTNET_Request : IBaiduRequest
    {
        protected Uri thisUri;
        public Baidu_DOTNET_Request()
        {
            Uri.TryCreate(baseUri, "item/.NET", out thisUri);
        }
        public override async Task GetAsync()
        {
            var request = await base.httpClient.GetAsync(thisUri);
            return request.StatusCode;
        }
    }
    public class Baidu_Microsoft_Request : IBaiduRequest
    {
        protected Uri thisUri;
        public Baidu_Microsoft_Request()
        {
            Uri.TryCreate(baseUri, "item/Microsoft", out thisUri);
        }
        public override async Task GetAsync()
        {
            var request = await base.httpClient.GetAsync(thisUri);
            return request.StatusCode;
        }
    }
    #endregion
    #region 访问 QQ 

    public abstract class IQQRequest : IRequest
    {
        protected HttpClient httpClient = new HttpClient();
        protected Uri baseUri = new Uri("https://new.qq.com/");
        public abstract Task GetAsync();
    }
    public class QQ_Images_Request : IQQRequest
    {
        protected Uri thisUri;
        public QQ_Images_Request()
        {
            Uri.TryCreate(baseUri, "ch/photo", out thisUri);
        }
        public override async Task GetAsync()
        {
            var request = await base.httpClient.GetAsync(thisUri);
            return request.StatusCode;
        }
    }
    public class QQ_OMN_Request : IQQRequest
    {
        protected Uri thisUri;
        public QQ_OMN_Request()
        {
            Uri.TryCreate(baseUri, "omn/author/5114481", out thisUri);
        }
        public override async Task GetAsync()
        {
            var request = await base.httpClient.GetAsync(thisUri);
            return request.StatusCode;
        }
    }

    #endregion

    #region 工厂模式和抽象工厂模式

    // 访问百度的工厂模式
    public class CreateBaidu : ICreateFactory
    {
        public IRequest One()
        {
            return new Baidu_DOTNET_Request();
        }
        public IRequest Two()
        {
            return new Baidu_Microsoft_Request();
        }
    }
    // 访问QQ的工厂模式
    public class CreateQQ : ICreateFactory
    {
        public IRequest One()
        {
            return new QQ_Images_Request();
        }
        public IRequest Two()
        {
            return new QQ_OMN_Request();
        }
    }

    public enum UrlType
    {
        BAIDU = 1,
        QQ = 2
    }

    // 抽象工厂模式
    public static class FactoryFactory
    {
        public static ICreateFactory Create(UrlType type)
        {
            switch (type)
            {
                case UrlType.BAIDU:
                    return new CreateBaidu();
                case UrlType.QQ:
                    return new CreateQQ();
            }
            return default;
        }
    }
    #endregion
}

工厂模式和抽象工厂模式的变体很多。

工厂模式是一层,可以通过工厂类创建类型;

抽象工厂模式是通过工厂模式创建一个工厂(一层),这个工厂继续创建新的工厂(二层),然后再创建类型。

痴者工良

高级程序员劝退师

文章评论