Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 抽象工厂模式-具体产品之间的依赖关系_C#_Oop_Design Patterns_Language Agnostic_Factory Pattern - Fatal编程技术网

C# 抽象工厂模式-具体产品之间的依赖关系

C# 抽象工厂模式-具体产品之间的依赖关系,c#,oop,design-patterns,language-agnostic,factory-pattern,C#,Oop,Design Patterns,Language Agnostic,Factory Pattern,请阅读下面的代码,问题在最后 using System; using System.Collections.Generic; namespace Graphics { public interface IGraphicsFactory { ICanvas CreateCanvas(); Square CreateSquare(); ComposedShape CreateComposedShape(); } pu

请阅读下面的代码,问题在最后

using System;
using System.Collections.Generic;

namespace Graphics
{
    public interface IGraphicsFactory
    {
        ICanvas CreateCanvas();
        Square CreateSquare();
        ComposedShape CreateComposedShape();
    }

    public class SimpleGraphicsFactory : IGraphicsFactory
    {
        public Square CreateSquare()
        {
            return new SimpleImpl.SimpleSquare();
        }

        public ComposedShape CreateComposedShape()
        {
            return new SimpleImpl.SimpleComposedShape();
        }

        public ICanvas CreateCanvas()
        {
            return new SimpleImpl.SimpleCanvas();
        }
    }

    public interface ICanvas
    {
        void AddShape(ShapeBase shape);
        void Render();
    }

    public abstract class ShapeBase
    {
        public abstract void Paint(ICanvas canvas);
    }

    public abstract class Square : ShapeBase
    {
        public int size;
    }

    public abstract class ComposedShape : ShapeBase
    {
        public int size;
        public ShapeBase InternalShape1 { get; set; }
        public ShapeBase InternalShape2 { get; set; }
    }
}


namespace Graphics.SimpleImpl
{
    internal class SimpleSquare : Graphics.Square
    {
        public void Init()
        {
            // do something really important
        }

        public override void Paint(ICanvas canvas)
        {
            Init();

            //?? how to avoid the type cast? (and I want to keep the DrawLine out of the ICanvas interface)
            SimpleCanvas scanvas = (canvas as SimpleCanvas);
            scanvas.DrawLine();
            scanvas.DrawLine();
            scanvas.DrawLine();
            scanvas.DrawLine();
        }
    }

    internal class SimpleComposedShape : Graphics.ComposedShape
    {
        public void Init()
        {
            //?? how can I call `InternalShape1.Init', preferably without type casts? (and I want to keep `Init` out of the `ShapeBase` class)
            // this.InternalShape1.Init();
            // this.InternalShape2.Init();
        }

        public override void Paint(ICanvas canvas)
        {
            Init();
            // TODO: draw the thing
        }
    }

    internal class SimpleCanvas : Graphics.ICanvas
    {
        List<ShapeBase> shapes = new List<ShapeBase>();

        public void AddShape(ShapeBase shape)
        {
            shapes.Add(shape);
        }

        public void Render()
        {
            foreach (ShapeBase s in shapes)
            {
                s.Paint(this);
            }
        }


        public void DrawLine()
        {
        }
    }
}


namespace Test
{
    using Graphics;
    class TestSimpleGraphics
    {
        static void Test1()
        {
            IGraphicsFactory fact = new SimpleGraphicsFactory();
            ICanvas canvas = fact.CreateCanvas();

            Square sq1 = fact.CreateSquare();
            Square sq2 = fact.CreateSquare();
            ComposedShape cs = fact.CreateComposedShape();
            cs.InternalShape1 = sq1;
            cs.InternalShape2 = sq2;

            canvas.AddShape(cs);
            canvas.Paint();
        }
    }
}
使用系统;
使用System.Collections.Generic;
名称空间图形
{
公共接口IGF工厂
{
ICanvas CreateCanvas();
Square创建Square();
ComposedShape创建ComposedShape();
}
公共类SimpleGraphicFactory:IGraphicsFactory
{
公共广场
{
返回新的SimpleImpl.SimpleSquare();
}
public ComposedShape CreateComposedShape()
{
返回新的SimpleImpl.SimpleComposedShape();
}
公共ICanvas CreateCanvas()
{
返回新的SimpleImpl.SimpleCanvas();
}
}
公共接口ICanvas
{
void AddShape(ShapeBase shape);
void Render();
}
公共抽象类形状库
{
公共抽象空白涂料(ICanvas帆布);
}
公共抽象类:ShapeBase
{
公共整数大小;
}
公共抽象类ComposedShape:ShapeBase
{
公共整数大小;
公共ShapeBase InternalShape1{get;set;}
公共ShapeBase InternalShape2{get;set;}
}
}
namespace Graphics.simplempl
{
内部类SimpleSquare:Graphics.Square
{
公共void Init()
{
//做一些真正重要的事情
}
公共覆盖无效绘制(ICanvas画布)
{
Init();
//??如何避免类型转换?(我想将抽绳保留在ICanvas界面之外)
SimpleCanvas scanvas=(画布为SimpleCanvas);
scanvas.drawine();
scanvas.drawine();
scanvas.drawine();
scanvas.drawine();
}
}
内部类SimpleComposedShape:Graphics.ComposedShape
{
公共void Init()
{
//?我如何调用'InternalShape1.Init',最好是不使用类型转换?(我想将'Init'排除在'ShapeBase'类之外)
//this.InternalShape1.Init();
//this.InternalShape2.Init();
}
公共覆盖无效绘制(ICanvas画布)
{
Init();
//托多:画那个东西
}
}
内部类SimpleCanvas:Graphics.ICanvas
{
列表形状=新列表();
公共空白添加形状(形状基形状)
{
形状。添加(形状);
}
公共无效呈现()
{
foreach(形状中的形状基)
{
s、 油漆(这个);
}
}
公共空水位线()
{
}
}
}
名称空间测试
{
使用图形;
类TestSimpleGraphics
{
静态void Test1()
{
IGraphicsFactory事实=新的SimpleGraphicsFactory();
ICanvas canvas=fact.CreateCanvas();
Square sq1=fact.CreateSquare();
Square sq2=fact.CreateSquare();
ComposedShape cs=fact.CreateComposedShape();
cs.InternalShape1=sq1;
cs.InternalShape2=sq2;
canvas.AddShape(cs);
canvas.Paint();
}
}
}
  • 我的抽象工厂模式实现正确吗
  • 内部
    SimpleSquare.Paint
    :是否可以避免类型转换?(我想把
    抽绳
    放在
    ICanvas
    界面之外)
  • 内部
    SimpleComposedShape.Init
    :如何调用
    InternalShape.Init
    ,最好不使用类型转换?(我想将
    Init
    排除在
    ShapeBase
    类之外)

  • 1-我认为你的
    SimpleGraphicsFactory
    确实是一个抽象工厂的好例子

    2-将
    SimpleSquare
    转换为
    SimpleCanvas
    是完全合适的,因为它们都是由同一家混凝土工厂创建的同一“系列”的一部分。回想一下抽象工厂的定义(重点是我的):

    提供用于创建相关族或从属族的接口 对象,而不指定其具体类

    此设计模式的含义是,它创建的类可以假定/要求它们与来自同一族的类一起使用

    使用.NET世界中的另一个例子,
    System.Data
    名称空间以类似的方式工作。
    System.Data.Sql
    命名空间中的对象将无法与System.Data.Oracle中的对象一起使用。如果需要
    OracleParameter
    ,则不能传递
    SqlParameter
    。您可以选择族并留在族中


    我不知道你想做什么,你;我需要详细的评论,我会修改我的回答。我希望一个
    ComposedShape
    有一个方法
    Add(Shape s)
    ,允许调用者向复合(容器)中添加多个形状。但也许我误解了。

    1-我认为您的
    SimpleGraphicsFactory
    确实是一个抽象工厂的好例子

    2-将
    SimpleSquare
    转换为
    SimpleCanvas
    是完全合适的,因为它们都是由同一家混凝土工厂创建的同一“系列”的一部分。回想一下抽象工厂的定义(重点是我的):

    提供用于创建相关族或从属族的接口 对象,而不指定其具体类

    此设计模式的含义是,它创建的类可以假定/要求它们与来自同一族的类一起使用

    使用.NET世界中的另一个例子,
    System.Data
    名称空间以类似的方式工作。
    System.Data.Sql
    命名空间中的对象将无法与System.Data.Oracle中的对象一起使用。您不能传递
    SqlParameter
    ,其中
    OracleParameter
    是expe
    interface ICanvas
    {
         void Clear();
         void DrawLine(Point from, Point to, Pen pen);
         void DrawCircle(Point center, Double radius, Pen pen);
         void Paint();
         /* and stuff like that */
    }
    
    class BitmapCanvas : ICanvas
    {
        private readonly byte[] _bitmapData;
        private readonly List<IBitmapShape> _primitives;
    
        public BitmapCanvas(int width, int height)
        {
            _bitmapData = new byte[width * height];
            _primitives = new List<IPrimitiveShape>();
        }
    
        public void DrawLine(...) 
        {
            // different implementations will handle this part differently.
            _primitives.Add(new BitmapLine(_bitmapData, from, to, pen));
        }
    
        public void Paint()
        {
            Clear(_bitmapData);
            foreach (var shape in _primitives)
                shape.Draw();
        }
    }
    
    class BitmapLine : IBitmapShape
    {
        public void Draw()
        {
            // write to the underlying byte array
        }
    }