nprogram’s blog

気ままに、プログラミングのトピックについて書いていきます

Compositeパターン [C#]

Compositeパターン

Compositeパターンは、容器と中身を同一視して、再帰的な構造を作るパターンです。 利用者は容器と中身を意識せずに使用することができます。

Compositeパターンを使用しない場合は、容器と中身を意識する必要がある。 コード例では、DirecotryクラスのListに追加したインスタンスがフォルダーなのか、ファイルなのか、判定する処理が発生します。

クラス図

f:id:nprogram:20181112224053p:plain

クラス説明

クラス名 クラス説明
IEntry FolderとFileを同一視するインターフェース
Directory フォルダークラス
File ファイルクラス
Program ユーザークラス

実行イメージ

f:id:nprogram:20181107222825p:plain

コード例

using System;
using System.Collections.Generic;

namespace Composite
{
    class Program
    {
        static void Main(string[] args)
        {
            Directory root = new Directory("root");
            Directory dir1 = new Directory("dir1");
            Directory dir2 = new Directory("dir2");
            Directory dir3 = new Directory("dir3");

            File file1 = new File("file1");
            File file2 = new File("file2");
            File file3 = new File("file3");
            File file4 = new File("file4");

            // フォルダーを追加する
            root.AddEntry(dir1);
            root.AddEntry(dir2);
            dir2.AddEntry(dir3);

            // ファイルを追加する
            root.AddEntry(file1);
            root.AddEntry(file2);
            dir2.AddEntry(file3);
            dir3.AddEntry(file4);

            root.Output(0);

            Console.ReadLine();
        }
    }

    public interface IEntry
    {
        void Output(int someDepth);
    }


    public class Directory : IEntry
    {
        private string Name = null;
        private List<IEntry> Entries = new List<IEntry>();

        public Directory(string someName)
        {
            this.Name = someName;
        }

        public void AddEntry(IEntry someEntry)
        {
            Entries.Add(someEntry);
        }

        public void Output(int someDepth)
        {
            for (int i = 0; i < someDepth; i++)
            {
                Console.Write("    ");
            }

            Console.WriteLine("{0} : {1}", this.GetType().ToString(), this.Name);

            foreach (var item in Entries)
            {
                // 階層を1つ深くする
                item.Output(someDepth + 1);
            }
        }
    }

    public class File : IEntry
    {
        private string Name = null;

        public File(string someName)
        {
            this.Name = someName;
        }

        public void Output(int someDepth)
        {
            for (int i = 0; i < someDepth; i++)
            {
                Console.Write("    ");
            }

            Console.WriteLine("{0} : {1}", this.GetType().ToString(), this.Name);
        }
    }
}

参考ページ

Abstract Factory パターン [C#]

Abstract Factory パターン [C#]

Abstract Factory パターンを記載します。

Abstract Factoryパターンを使うことによって、クラスの使用者は、具象クラスを直接扱わずに、具職クラスのインスタンスを取得できる。
(Main関数で扱っているのは、抽象クラスのみである。)

クラス図

f:id:nprogram:20181104232706p:plain

実行イメージ

f:id:nprogram:20181104235003p:plain

using System;
using System.Collections.Generic;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            CurryRiceAbstractFactory tomatoCurry = CreateFactory("Tomato Curry Rice");
            tomatoCurry.Order();


            CurryRiceAbstractFactory indianCurryRice = CreateFactory("Indian Curry Rice");
            indianCurryRice.Order();

            Console.ReadLine();
        }

        private static CurryRiceAbstractFactory CreateFactory(String str)
        {
            if (str == "Tomato Curry Rice")
            {
                return new TomatoCurryFactory(str);
            }
            else if (str == "Indian Curry Rice")
            {
                return new IndianCurryRice(str);
            }

            return null;
        }

        public abstract class CurryRiceAbstractFactory
        {
            private string Name;
            private Soup Soup;
            private List<Spice> SpiceList = new List<Spice>();
            private List<Ingredients> IngredientsList = new List<Ingredients>();
            private List<Vegetable> VegetableList = new List<Vegetable>();


            abstract public Soup GetSoup();
            abstract public List<Spice> GetSpiceList();
            abstract public List<Ingredients> GetIngredientsList();
            abstract public List<Vegetable> GetVegetableList();

            public void Order()
            {
                Console.WriteLine("---- Get a " + GetName() + " Recipe ----");
                GetRecipe();
                Console.WriteLine();

                Console.WriteLine("---- Cooking a " + GetName() + " ----");
                Cut();
                StirFry();
                Boil();
                Serve();
                Console.WriteLine();
            }

            public string GetName()
            {
                return this.Name;
            }

            public void SetName(string someName)
            {
                this.Name = someName;
            }

            public void Cut()
            {
                Console.WriteLine("Cut");
            }

            public void Boil()
            {
                Console.WriteLine("Boil");
            }

            public void StirFry()
            {
                Console.WriteLine("Stir fry");
            }

            public void Serve()
            {
                Console.WriteLine("Here you are. This is " + GetName());
            }

            public void GetRecipe()
            {
                Console.WriteLine("---- Soup ----");
                Console.WriteLine(GetSoup().Name);

                Console.WriteLine("---- Spice ----");
                GetSpiceList().ForEach(item =>
                {
                    Console.WriteLine(item.Name);

                });

                Console.WriteLine("---- Ingredients ----");
                GetIngredientsList().ForEach(item =>
                {
                    Console.WriteLine(item.Name);

                });

                Console.WriteLine("---- Vegetable ----");
                GetVegetableList().ForEach(item =>
                {
                    Console.WriteLine(item.Name);

                });
            }
        }

        public class TomatoCurryFactory : CurryRiceAbstractFactory
        {
            public TomatoCurryFactory(string str)
            {
                SetName(str);
            }

            public override Soup GetSoup()
            {
                return new TomatoSoup();
            }

            public override List<Spice> GetSpiceList()
            {
                List<Spice> list = new List<Spice>();

                list.Add(new GaramMasala());
                list.Add(new Turmeric());

                return list;
            }

            public override List<Ingredients> GetIngredientsList()
            {
                List<Ingredients> list = new List<Ingredients>();

                list.Add(new Pork());

                return list;
            }

            public override List<Vegetable> GetVegetableList()
            {
                List<Vegetable> list = new List<Vegetable>();

                list.Add(new Tomato());
                list.Add(new Carrot());

                return list;
            }

        }

        public class IndianCurryRice : CurryRiceAbstractFactory
        {
            public IndianCurryRice(string str)
            {
                SetName(str);
            }

            public override Soup GetSoup()
            {
                return new OnionSoup();
            }

            public override List<Spice> GetSpiceList()
            {
                List<Spice> list = new List<Spice>();

                list.Add(new GaramMasala());
                list.Add(new Turmeric());

                return list;
            }

            public override List<Ingredients> GetIngredientsList()
            {
                List<Ingredients> list = new List<Ingredients>();

                list.Add(new Chicken());

                return list;
            }

            public override List<Vegetable> GetVegetableList()
            {
                List<Vegetable> list = new List<Vegetable>();

                list.Add(new Tomato());
                list.Add(new Carrot());
                list.Add(new GreenPapper());

                return list;
            }
        }

        #region Spice
        public abstract class Spice
        {
            public string Name;
            public string Color;
        }

        public class GaramMasala : Spice
        {
            public GaramMasala()
            {
                this.Name = "Garam masala";
                this.Color = "Yellow";
            }

        }

        public class Turmeric : Spice
        {
            public Turmeric()
            {
                this.Name = "Turmeric";
                this.Color = "Yellow";
            }
        }
        #endregion Spice

        #region Soup
        public abstract class Soup
        {
            public string Name;
        }

        public class OnionSoup : Soup
        {
            public OnionSoup()
            {
                this.Name = "Onion soup";
            }
        }

        public class TomatoSoup : Soup
        {
            public TomatoSoup()
            {
                this.Name = "Tomato soup";
            }
        }
        #endregion Soup

        #region Ingredients
        public abstract class Ingredients
        {
            public string Name;
        }

        public class Pork : Ingredients
        {
            public Pork()
            {
                this.Name = "Pork";
            }
        }

        public class Beef : Ingredients
        {
            public Beef()
            {
                this.Name = "Beef";
            }
        }

        public class Chicken : Ingredients
        {
            public Chicken()
            {
                this.Name = "Chicken";
            }
        }
        #endregion Ingredients

        #region Vegetables
        public abstract class Vegetable
        {
            public string Name;
        }

        public class Carrot : Vegetable
        {
            public Carrot()
            {
                this.Name = "Carrot";
            }
        }

        public class GreenPapper : Vegetable
        {
            public GreenPapper()
            {
                this.Name = "GreenPapper";
            }
        }

        public class Tomato : Vegetable
        {
            public Tomato()
            {
                this.Name = "Tomato";
            }
        }
        #endregion Vegetables
    }
}

以下の記事に記載されています。

http://www.techscore.com/tech/DesignPattern/AbstractFactory.html/

Factory Methodパターン [C#]

Factory Methodパターン

インスタンス化したいオブジェクト(製品)を実行時の条件によって決めたい場合に利用します。
Factory Methodパターンはオブジェクト(製品)を生成する側と利用する側に分けて定義する必要があります。
分けておくことで、将来システムに起こりえる変更をあらかじめ分離でき保守性を保つことができます。

パターン構造

f:id:nprogram:20181111234203p:plain

構成要素

  • Product : 生成されるオブジェクト(製品)のAPIを定義する抽象クラス。製品の具象クラスが抽象クラスで使用できるようにする
  • ConcreteProduct : 生成される具象製品クラス
  • Creator : ファクトリメソッドを除く製品を操作するAPI抽象クラスを定義する抽象クラス
  • ConcreteCreator : ファクトリメソッドを実装し、実際に製品を作成するクラス

クラス図

f:id:nprogram:20181112000559p:plain

実行結果イメージ

f:id:nprogram:20181031160253p:plain

コード

using System;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Pizza pizza;
            NYPizzaFactory NYPizzaFactory = new NYPizzaFactory();
            ChicagoPizzaFactory ChicagoPizzaFactory = new ChicagoPizzaFactory();

            pizza = NYPizzaFactory.OrderPizza("Cheese");
            pizza = ChicagoPizzaFactory.OrderPizza("Cheese");
            Console.ReadLine();
        }
    }

    /// <summary>
    /// ピザを作成するファクトリークラス (抽象クラス)
    /// </summary>
    public abstract class PizzaStore
    {
        public abstract Pizza CreatePizza(string type);

        public Pizza OrderPizza(string type)
        {
            Pizza pizza;

            pizza = CreatePizza(type);

            if (pizza == null) return null;

            // すべてのピザに対して
            pizza.Prepare();
            pizza.Bake();
            pizza.Cut();
            pizza.Box();

            return pizza;
        }
    }

    /// <summary>
    /// ニューヨークのピザファクトリークラス (具象クラス)
    /// </summary>
    public class NYPizzaFactory : PizzaStore
    {
        public override Pizza CreatePizza(string type)
        {
            Pizza pizza = null;

            if (type == "Cheese")
            {
                pizza = new NYStyleCheesePizza(type);

            }
            else if (type == "Tomato")
            {
                pizza = new NYStyleCheesePizza(type);
            }

            return pizza;
        }
    }

    /// <summary>
    /// シカゴのピザファクトリークラス
    /// </summary>
    public class ChicagoPizzaFactory : PizzaStore
    {
        public override Pizza CreatePizza(string type)
        {
            Pizza pizza = null;

            if (type == "Cheese")
            {
                pizza = new ChicagoStyleCheesePizza(type);

            }
            else if (type == "Tomato")
            {
                pizza = new ChicagoStyleCheesePizza(type);
            }

            return pizza;
        }
    }

    /// <summary>
    /// 抽象Pizzaクラス。
    /// </summary>
    public abstract class Pizza
    {
        /// <summary>
        /// ピザの名前
        /// </summary>
        public string Name;

        /// <summary>
        /// ピザの生地の厚さ
        /// </summary>
        public string Thickness;

        /// <summary>
        /// ピザのチーズ量
        /// </summary>
        public string AmountOfCheese;

        /// <summary>
        /// スタイル
        /// </summary>
        /// <remarks>
        /// ニューヨーク風、シカゴ風など
        /// </remarks>
        public string Style;


        public void Prepare()
        {
            Console.WriteLine(this.Style + "ピザの作成を開始します。");
            Console.WriteLine(this.Name + "ピザの材料を準備します。");
            Console.WriteLine("ピザの生地は" + this.Thickness + "します。");
            Console.WriteLine("チーズ量は" + this.AmountOfCheese + "します。");
        }

        public void Bake()
        {
            Console.WriteLine(this.Name + "ピザを焼きます。");
        }

        public void Cut()
        {
            Console.WriteLine(this.Name + "ピザをカットします。");
        }

        public void Box()
        {
            Console.WriteLine(this.Name + "ピザを箱に収納します。");
            Console.WriteLine();
        }
    }

    /// <summary>
    /// 具象Pizzaクラス (チーズピザ : ニューヨーク風)
    /// </summary>
    public class NYStyleCheesePizza : Pizza
    {
        public NYStyleCheesePizza(string someName)
        {
            this.Name = someName;
            this.Style = "ニューヨーク風";
            this.Thickness = "薄く";
            this.AmountOfCheese = "少なく";
        }
    }

    /// <summary>
    /// 具象Pizzaクラス (トマトピザ : ニューヨーク風)
    /// </summary>
    public class NYStyleTomatoPizza : Pizza
    {

        public NYStyleTomatoPizza(string someName)
        {
            this.Name = someName;
            this.Style = "ニューヨーク風";
            this.Thickness = "薄く";
            this.AmountOfCheese = "少なく";
        }
    }
    /// <summary>
    /// 具象Pizzaクラス (チーズピザ : シカゴ風)
    /// </summary>
    public class ChicagoStyleCheesePizza : Pizza
    {

        public ChicagoStyleCheesePizza(string someName)
        {
            this.Name = someName;
            this.Style = "シカゴ風";
            this.Thickness = "厚く";
            this.AmountOfCheese = "多く";
        }
    }

    /// <summary>
    /// 具象Pizzaクラス (トマトピザ : シカゴ風)
    /// </summary>
    public class ChicagoStyleTomatoPizza : Pizza
    {

        public ChicagoStyleTomatoPizza(string someName)
        {
            this.Name = someName;
            this.Style = "シカゴ風";
            this.Thickness = "厚く";
            this.AmountOfCheese = "多く";
        }
    }
}

参考リンク

https://gist.github.com/fujimisakari

事例で学ぶデザインパターン 第 4 回 | オブジェクトの広場

Simple Factory (C#)

Simple Factoryパターンについて

実際にはデザインパターンではありません。プログラミングのイディオムとなります。

クラス図

f:id:nprogram:20181031134028p:plain

実行イメージ

f:id:nprogram:20181031133012p:plain

コードの説明

以下のコードは、ファクトリーのクライアントクラスです。 以下のコードで、Pizza pizza変数を宣言しておりますが、Pizzaクラスは実体がない抽象クラスです。 実体(具象Pizzaクラス:ここでは、CheesePizzaクラスのこと)は、ファクトリークラスのみが生成可能であるべきです。

Pizza pizza = factory.createPizza(type);

    /// <summary>
    /// ファクトリーのクライアントクラス
    /// </summary>
    public class PizzaStores
    {
        SimplePizzaFactory factory = new SimplePizzaFactory();

        public Pizza orderPizza(string type)
        {

            Pizza pizza = factory.createPizza(type);

            if (pizza == null) return null;

            pizza.Prepare();
            pizza.Bake();
            pizza.Cut();
            pizza.Box();

            return pizza;
        }
    }

コード

using System;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            PizzaStores pizzaStores = new PizzaStores();
            Pizza pizza;

            pizza = pizzaStores.orderPizza("Cheese");

            pizza = pizzaStores.orderPizza("Tomato");

            Console.ReadLine();
        }
    }

    /// <summary>
    /// ファクトリーのクライアントクラス
    /// </summary>
    public class PizzaStores
    {
        SimplePizzaFactory factory = new SimplePizzaFactory();

        public Pizza orderPizza(string type)
        {

            Pizza pizza = factory.createPizza(type);

            if (pizza == null) return null;

            pizza.Prepare();
            pizza.Bake();
            pizza.Cut();
            pizza.Box();

            return pizza;
        }
    }

    /// <summary>
    /// ピザを作成するファクトリークラス
    /// </summary>
    /// <remarks>
    /// このクラスは、具象Pizzaクラス(CheesePizaクラスとか、TomatoPizzaクラス)を参照するアプリケーションで唯一のクラスであるべき
    /// </remarks>
    public class SimplePizzaFactory
    {
        public Pizza createPizza(string type)
        {
            Pizza pizza = null;

            if (type == "Cheese")
            {
                pizza =  new CheesePizza(type);

            }
            else if (type == "Tomato")
            {
                pizza = new CheesePizza(type);
            }

            return pizza;
        }
    }

    /// <summary>
    /// 抽象Pizzaクラス。
    /// </summary>
    public abstract class Pizza
    {
        /// <summary>
        /// ピザの名前
        /// </summary>
        public string Name;

        public void Prepare()
        {
            Console.WriteLine(this.Name + "ピザの材料を準備します。");
        }

        public void Bake()
        {
            Console.WriteLine(this.Name + "ピザを焼きます。");
        }

        public void Cut()
        {
            Console.WriteLine(this.Name + "ピザをカットします。");
        }

        public void Box()
        {
            Console.WriteLine(this.Name + "ピザを箱に収納します。");
        }
    }

    /// <summary>
    /// 具象Pizzaクラス
    /// </summary>
    public class CheesePizza : Pizza
    {

        public CheesePizza(string someName)
        {
            this.Name = someName;
        }
    }

    /// <summary>
    /// 具象Pizzaクラス
    /// </summary>
    public class TomatoPizza : Pizza
    {

        public TomatoPizza(string someName)
        {
            this.Name = someName;
        }
    }

}

Template Method パターン [C#]

TemplateMethodパターンとは

Template Method パターンの目的は、ある処理のおおまかなアルゴリズムをあらかじめ決めておいて、
そのアルゴリズムの具体的な設計をサブクラスに任せることである。そのため、システムのフレームワークを構築するための手段としてよく活用される。

抽象メソッドとは、実装を持たず、メソッドの意味(規約)だけを定義したメソッドです。 抽象メソッドの実装は基底クラスでは行わず、派生クラスで行います。
また、抽象クラスとは、 インスタンスを生成出来ないクラスのことで、 継承して使うことを前提としたクラスのことです。

サンプル例

小型トラック(2tトラック)と大型トラック(10tトラック)を作ろうとしたとき、特定の順序ですべて作成してほしい場合に役立ちます。 サンプルコードでは、以下の順序でトラックを作成します。

(1) パーツを購入する (2) パーツを加工する (3) 組み立てる (4) 塗装する

クラス図

抽象クラスは、TemplateMethodMakeCarクラスです。サブクラス(BigTrackクラス、SmallTrackクラス)に具体的な設計を任せます。

f:id:nprogram:20181108064902p:plain

コード

using System;

namespace TemplateMethodOriginal
{
    class Program
    {
        static void Main(string[] args)
        {
            BigTrack BigTrack = new BigTrack();
            BigTrack.createMakeCar();

            SmallTrack SmallTrack = new SmallTrack();
            SmallTrack.createMakeCar();


            // 実行が一瞬で終わって確認できないので、キーの入力を待ちます
            Console.ReadLine();
        }
    }
    public abstract class TemplateMethodMakeCar
    {
        protected abstract void BuyParts();
        protected abstract void MakeParts();
        protected abstract void Assemble();
        protected abstract void PaintBody();

        public void createMakeCar()
        {
            BuyParts();
            MakeParts();
            Assemble();
            PaintBody();
        }
    }

    public class BigTrack : TemplateMethodMakeCar
    {
        override protected void BuyParts()
        {
            Console.WriteLine("大型トラックの部品を購入する");
        }

        override protected void MakeParts()
        {
            Console.WriteLine("大型トラックの部品を加工する");
        }
        override protected void Assemble()
        {
            Console.WriteLine("大型トラックの組み立てる");
        }
        override protected void PaintBody()
        {
            Console.WriteLine("大型トラックの塗装する");
        }
    }

    public class SmallTrack : TemplateMethodMakeCar
    {
        override protected void BuyParts()
        {
            Console.WriteLine("小型トラックの部品を購入する");
        }

        override protected void MakeParts()
        {
            Console.WriteLine("小型トラックの部品を加工する");
        }
        override protected void Assemble()
        {
            Console.WriteLine("小型トラックの組み立てる");
        }
        override protected void PaintBody()
        {
            Console.WriteLine("小型トラックの塗装する");
        }
    }
}

f:id:nprogram:20181028162858p:plain

Python基礎学習 (クラスについて)

クラスについて

Pythonでもクラスはあります。
クラスをインスタンス化して、オブジェクトを生成します。
クラスを生成したときに呼び出されるクラスのコンストラクタ処理(初期化処理)は、'''def init(self):'''の形式で呼び出されます。
__init__()にかかわらず、すべてのメソッドの決まりとして、第一パラメータは、selfと記述します。
これは、メソッド呼び出し時に、呼び出し元のオブジェクトが渡されるというPythonのしきたりによるものです。

また、Pythonでは、C++でいうオーバーロードの仕組みがないため、デフォルト引数を使用してオーバーロードを実現します。

class Car:

    def __init__(self, speed=0, time_span=0, distance=0):
        self.speed = speed
        self.time_span = time_span
        self.distance = distance

    def run(self, speed, time_span):
        self.speed = speed
        self.time_span = time_span
        self.distance = speed * time_span

    def show_speed(self):
        print('Speed : ' + str(self.speed))

    def show_time_span(self):
        print('Speed : ' + str(self.time_span))

    def show_distance(self):
        print('Distance : ' + str(self.distance))


car1 = Car()
car1.run(10, 5)
car1.show_speed()
car1.show_time_span()
car1.show_distance()

car2 = Car()
car2.run(10, 10)
car2.show_speed()
car2.show_time_span()
car2.show_distance()

# 実行結果
# Speed : 10
# Speed : 5
# Distance : 50
# Speed : 10
# Speed : 10
# Distance : 100

Pythonでシグモイド関数とシグモイド関数の微分をグラフで書く

はじめに

人工知能のアルゴリズムでは、シグモイド関数とシグモイド関数の微分が大切みたいです。

コードをメモっておきます。

なお、以下のコードで、でグラフの見出しを作成することが可能です。 複数のデータ例がある場合に、便利です。

plt.plot(x, y_sig, label="sigmoid")
plt.plot(x, dy_sig, label="d_sigmoid")
plt.legend()

コード

import matplotlib.pyplot as plt
import numpy as np
import math


# シグモイド関数
# y = 1 / (1 * + e^(-x))
def sigmoid(a):
    s = 1 / (1 + e**-a)
    return s


# シグモイド関数の微分
# dy_sig = sigmoid(x) * (1 - sigmoid(x))
def d_sigmoid(a):
    s = sigmoid(a) * (1 - sigmoid(a))
    return s


e = math.e
dx = 0.1

x = np.arange(-10, 10, dx)

y_sig = sigmoid(x)
dy_sig = d_sigmoid(x)

plt.plot(x, y_sig, label="sigmoid")
plt.plot(x, dy_sig, label="d_sigmoid")
plt.legend()
plt.show()

イメージ

f:id:nprogram:20180928081353p:plain