Visual Studio Code ターミナルでファイルを表示すると文字化けしていた場合の文字化け解消方法
文字化けの例
UTF-8のファイルをPoweShellで表示すると、次のように文字化けしていました。
文字化けの解消方法
文字化けを解消するため、読み込むファイルのエンコードを変更します。
VSCodeでそのファイルを開いて、VSCode画面下の「UTF-8」の部分をクリックします。
下記のように選択肢が表示されるので「エンコード付きで保存」を選択します。
PowerShellで開く場合、SJIS・UTF-8BOM・UTF-16のファイルであれば設定を変更せずに読み込めます。
今回はUTF-8 with BOMを選択しました。
SJIS・UTF-16でも同様に文字化けしないことが確認できました。
再度、文字化けしていたファイルを表示すると、文字化けが解消されたことが確認できました。
参考にした記事:
デザインパターン:Template Method(テンプレートメソッド)パターン
Template Methodパターンとは
- Template Methodパターンは、テンプレートの機能を持つパターンです。
- スーパークラスの方にテンプレートとなるメソッドが定義されています。
- その定義の中では抽象メソッドが使われています。
- このため、スーパークラスのプログラムを読んでいるだけでは、最終的にどんな処理をすることになるかは分かりません。
- わかることは、抽象メソッドをどのように呼び出しているか、ということだけです。
- 抽象メソッドを実際に実装するのはサブクラスです。
- サブクラスの側でメソッドを実装すれば、具体的な処理が決定します。
- 異なるサブクラスが異なる実装を行えば、異なる処理が行われます。
- しかし、どのサブクラスでどのような実装をしたとしても、処理の大きな流れはスーパークラスで組み立てたとおりになります。
- このように、スーパークラスで処理の枠組みを定め、サブクラスでその具体的な内容を定めるようなデザインパターンを、「Template Methodパターン」と呼びます。
Template Methodパターンを使うメリットについて
ロジックが共通化できる
- スーパークラスのテンプレートメソッドでアルゴリズムが記述されているので、サブクラス側ではアルゴリズムをいちいち記述する必要がなくなります。
- もし、Template Methodパターンを使わず、複数のクラスにロジック部分をコピペしていると、バグが発見されたときに、ロジックが書かれているすべてのクラスを修正しなければならなくなります。
Template Methodパターンでプログラミングしていれば、テンプレートメソッドに誤りが発見された場合は、テンプレートメソッドのみ修正すればよいことになります。
サンプルプログラム
クラス一覧
名前 | 説明 |
---|---|
Shopping.java | メソッドtoShoppingのみ実装されている抽象クラス |
OnlineShop.java | メソッドchooseProduct, goToCashRegister, Payを実装しているクラス |
RealStore.java | メソッドchooseProduct, goToCashRegister, Payを実装しているクラス |
Main.java | 動作テスト用のクラス |
クラス図
Shopping.java
public abstract class Shopping { public abstract void chooseProduct(); public abstract void goToCashRegister(); public abstract void pay(); public void toShopping() { chooseProduct(); goToCashRegister(); pay(); } }
RealStore.java
public class RealStore extends Shopping { private String product; public RealStore(String product) { this.product = product; } @Override public void chooseProduct() { System.out.println("***リアル店舗でお買い物***\n"); System.out.println("陳列棚から「" + product + "」を選びました。"); } @Override public void goToCashRegister() { System.out.println("レジに並びます。\n人が少ない列に並びました。"); } @Override public void pay() { System.out.println("端末に電子マネーのカードをかざして支払いをしました。\n"); } }
OnlineShop.java
public class OnlineShop extends Shopping { private String product; public OnlineShop (String product) { this.product = product; } @Override public void chooseProduct() { System.out.println("***ネットショッピング***\n"); System.out.println("商品リストから「" + product + "」を選びました。"); } @Override public void goToCashRegister() { System.out.println("レジへ行くボタンを押下しました。"); } @Override public void pay() { System.out.println("クレジットカードで支払いをしました。\n"); } }
Main.java
public class Main { public static void main(String[] args) { Shopping sh1 = new RealStore("アイスクリーム"); Shopping sh2 = new OnlineShop("地方の名産品"); sh1.toShopping(); sh2.toShopping(); } }
実行結果
***リアル店舗でお買い物*** 陳列棚から「アイスクリーム」を選びました。 レジに並びます。 人が少ない列に並びました。 端末に電子マネーのカードをかざして支払いをしました。 ***ネットショッピング*** 商品リストから「地方の名産品」を選びました。 レジへ行くボタンを押下しました。 クレジットカードで支払いをしました。
参考:詳しくは、以下の書籍を参照してください
- 「補講:クラス階層と抽象クラス」も参考になります
- 練習問題もあります
デザインパターン:Prototype(プロトタイプ)パターン
Prototype パターンとは
クラスからインスタンスを生成するのではなく、インスタンスから別のインスタンスを作り出すパターンをPrototype(プロトタイプ)パターンと呼びます。
- prototypeという英単語は、「原型」や「模範」という意味です。
- prototypeのインスタンスを元に新しいインスタンスを作ります。
- Java言語では、複製を作る操作を「clone(クローン)」と呼びます。
- クラスのインスタンスを作成するとき、Javaでは、newというキーワードを使って、クラス名を指定することでインスタンスを生成します。
- 例えば、Somethingクラスのインスタンスを作成する場合は、次のような式を書きます。
new something()
- しかし、次のような場合、クラス名を指定せずにインスタンスを生成したくなる場合があります。
- 種類が多すぎてクラスにまとめられない場合
扱いたいオブジェクトの種類が多すぎて、1つ1つを別のクラスにすると、ソースファイルを多数作成することになり、ソースプログラムの管理がしにくくなる場合です。 - クラスからのインスタンス生成が難しい場合
ユーザーが操作して作った図形のインスタンスと同じものを再度、作りたいといった場合、 作ったインスタンスを保存しておき、作りたいときにそのインスタンスをコピーします。 - フレームワークと生成するインスタンスを分けたい場合
インスタンスを生成するときの】フレームワークを、特定のクラスに依存しないように作りたい場合、 前もって「ひな形」となるインスタンスを登録しておき、その登録したインスタンスをコピーすることでインスタンスを生成します。
- 種類が多すぎてクラスにまとめられない場合
Prototypeパターンのクラス図
- Prototype(プロトタイプ:原型)の役
インスタンスをコピー(複製)して新しいインスタンスを作るためのメソッドを定めます。 - ConcretePrototype(コンクリート・プロトタイプ:具体的な原型)の役
インスタンスをコピーして新しいインスタンスを作るメソッドを実装します。 - Client(クライアント:利用者)の役
インスタンスをコピーするメソッドを利用して、新しいインスタンスを作ります。
サンプルプログラム
以下、Prototypeパターンを使ったサンプルプログラムです。
クラスとインターフェース一覧
パッケージ | 名前 | 説明 |
---|---|---|
framework | Product | 抽象メソッドuseとcreateCloneが 宣言されているインターフェース |
framework | Manager | createCloneを使ってインスタンスを 複製するクラス |
無名 | ConcreteProduct | ・createCloneを実装 ・MessageBoxクラス等のスーパークラス |
無名 | MessageBox | ・文字列を枠線で囲って表示するクラス ・useとcreateCloneを実装 |
無名 | UnderlinePen | ・文字列に下線を引いて表示するクラス ・useとcreateCloneを実装 |
無名 | ReplayQuote | ・文字列の前に引用符を表示するクラス ・useとcreateCloneを実装 |
無名 | Main | 動作テスト用のクラス |
サンプルプログラムのクラス図
Productインタフェース
- java.lang.Cloneableインタフェースを継承しています。
- このインタフェースを実装しているクラスは、cloneメソッドを使用して自動的に複製ができるようになります。
- useメソッドは、名前のとおり「使う」ためのメソッドです。何をどのように「使う」かはサブクラスの実装に任されます。
- createCloneメソッドは、インスタンスの複製を行うためのものです。
Product.java
package SampleDesignPattern.framework; public interface Product extends Cloneable { public abstract void use(String s); public abstract Product createClone(); }
Managerクラス
- Managerクラスは、Productインターフェースを利用してインスタンスの複製を行うクラスです。
- showcaseフィールドは、java.util.HashMapでインスタンスの「名前」と「インスタンス」の対応関係を表現したものです。
- registerメソッドは、引数で渡された製品の名前とProductインターフェースの1組を登録します。
- Managerクラスには、Productインターフェースを実装した具体的なクラス名は出てきません。そのため、具体的なクラスとは独立に修正できることを意味しています。ソース中にクラスの名前を書いてしまうと、そのクラスと密接な関係ができてしまします。
- オブジェクト指向プログラミングの目標の1つである「部品としての再利用」をするため、ソースファイル(.java)がなくても、クラスファイル(.class)があれば再利用できる、ようにしています。
Manager.java
package SampleDesignPattern.framework; import java.util.HashMap; public class Manager { private HashMap<String, Product> showcase = new HashMap<String, Product>(); public void register(String name, Product proto) { showcase.put(name, proto); } public Product create(String protoname) { Product p = (Product)showcase.get(protoname); return p.createClone(); } }
ConcreteProduct
- サブクラスで実装するcreateCloneメソッドは共通の処理であるため、Productインターフェースを実装し、ここでcreateCloneを実装します。
- createCloneメソッドは、cloneメソッドを使用し、自分自身の複製を行うメソッドです。
- Java言語のcloneメソッドは、自分のクラス(およびサブクラス)からしか呼び出すことができないため、creageCloneメソッドを作成して、その中でcloneメソッドを使うようにしています。
- useメソッドは各サブクラスで処理内容が異なるため、抽象メソッドのままとします。
ConcreteProduct.java
package SampleDesignPattern.PrototypePattern; import SampleDesignPattern.framework.Product; public abstract class ConcreteProduct implements Product { public abstract void use(String s); @Override public Product createClone() { Product p = null; try { p = (Product)clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return p; } }
MessageBoxクラス
- 具体的なサブクラス。ConcreteProductクラスを継承しています。
- useメソッドは、引数で渡された文字列に対して、decocharフィールドの文字で囲みます。
MessageBox.java
package SampleDesignPattern.PrototypePattern; public class MessageBox extends ConcreteProduct { private char decochar; public MessageBox(char decochar) { this.decochar = decochar; } @Override public void use(String s) { int length = s.getBytes().length; for (int i = 0; i < length + 4; i++) { System.out.print(decochar); } System.out.println(""); System.out.println(decochar + " " + s + " " + decochar); for (int i = 0; i < length + 4; i++) { System.out.print(decochar); } System.out.println(""); } }
UnderlinePenクラス
- 具体的なサブクラス。ConcreteProductクラスを継承しています。
- useメソッドは、引数で渡された文字列に対して、二重引用符""でくくり、文字列の下にulcharフィールドの文字で下線を引きます。
UnderlinePen.java
package SampleDesignPattern.PrototypePattern; public class UnderlinePen extends ConcreteProduct { private char ulchar; public UnderlinePen(char ulchar) { this.ulchar = ulchar; } @Override public void use(String s) { int length = s.getBytes().length; System.out.println("\"" + s + "\""); System.out.print(" "); for (int i = 0; i < length; i++) { System.out.print(ulchar); } System.out.println(""); } }
ReplayQuoteクラス
- 具体的なサブクラス。ConcreteProductクラスを継承しています。
- useメソッドは、引数で渡された文字列の先頭にquotecharフィールドの文字を付与します。
ReplayQuote.java
package SampleDesignPattern.PrototypePattern; public class ReplayQuote extends ConcreteProduct { private char quotechar; public ReplayQuote(char quotechar) { this.quotechar = quotechar; } @Override public void use(String s) { System.out.println(quotechar + " " + s); } }
Mainクラス
- Managerのインスタンスを作ります。
- Managerのインスタンスに対して、UnderlinePenのインスタンス、MessageBoxのインスタンス、ReplayQuoteのインスタンスを名前付きで登録します。
名前 | クラス | インスタンスの内容 |
---|---|---|
"strong message" | UnderlinePen | ulchar:'~' |
"warning box" | MessageBox | decochar:'*' |
"slash box" | MessageBox | decochar:'/' |
"greater than quote" | ReplayQuote | quotechar:'>' |
Main.java
package SampleDesignPattern.ReplayQuotePrototypePattern; import SampleDesignPattern.framework.*; public class Main { public static void main(String[] args) { // 準備 Manager manager = new Manager(); UnderlinePen upen = new UnderlinePen('~'); MessageBox mBox = new MessageBox('*'); MessageBox sBox = new MessageBox('/'); ReplayQuote gQuotes = new ('>'); manager.register("strong message", upen); manager.register("warning box", mBox); manager.register("slash box", sBox); manager.register("greater than quote", gQuotes); // 生成 Product p1 = manager.create("strong message"); p1.use("Hello, World."); Product p2 = manager.create("warning box"); p2.use("Hello, world."); Product p3 = manager.create("slash box"); p3.use("Hello, world."); Product p4 = manager.create("greater than quote"); p4.use("Hello, world."); } }
【実行結果】
"Hello, World." ~~~~~~~~~~~~~ ***************** * Hello, world. * ***************** ///////////////// / Hello, world. / ///////////////// > Hello, world.
参考:詳しくは、以下の書籍を参照してください
- 「補講:cloneメソッドとjava.lang.Cloneableインターフェース」も参考になります
- 練習問題もあります
デザインパターン:Singleton(シングルトン)パターン
Singleパターンの概要
インスタンスが1個しか存在しないことを保証するパターンをSingletonパターンと呼びます。
singletonとは、要素を1個しかもたない集合のことです
サンプルプログラム
表 クラス一覧
名前 | 説明 |
---|---|
Singleton | インスタンスが1つしか存在しないクラス |
Main | 動作テスト用のクラス |
クラス図
以下、各クラスの説明
Singletonクラス
- インスタンスは1つしか作られません。
- staticフィールド(クラス変数)としてsingletonを定義し、Singletonクラスのインスタンスで初期化します。
- この初期化はSingletonクラスのロード時に一度だけ行われます。
- コンストラクタはprivateにします。privateにする理由は以下のとおりです。
- Singletonクラスの唯一のインスタンスを得るための static メソッドを定義します。ここでは、getInstance()という名前にしています。
Singleton.java
public class Singleton { private static Singleton singleton = new Singleton(); private Singleton() { System.out.println("インスタンスを生成しました"); } public static Singleton getInstance() { return singleton; } }
Mainクラス
- SingletonクラスのgetInstanceメソッドを呼び出しSingletonのインスタンスを取得します。
- インスタンスが1つしか存在しないことを確認するため、getInstanceメソッドを2回呼び出しそれぞれobj1とobj2に代入し、obj1 == obj2でテストしています。
Main.java
public class Main { public static void main(String[] args) { System.out.println("Singletonプログラム開始"); Singleton obj1 = Singleton.getInstance(); Singleton obj2 = Singleton.getInstance(); if (obj1 == obj2) { System.out.println("obj1とobj2は同じインスタンスです"); } else { System.out.println("obj1とobj2は異なるインスタンスです"); } System.out.println("Singletonプログラム終了"); } }
実行結果:
Singletonプログラム開始 コンストラクタ:インスタンスを生成しました obj1とobj2は同じインスタンスです Singletonプログラム終了
- プログラムが開始後、getInstanceメソッドを呼び出したときに Singletonクラスが初期化され static フィールドの初期化が行われ、唯一のインスタンスが生成されます。
- 実行結果から、Singletonパターンの目的どおりインスタンスが1つしか存在しないことを保証できることが確認できました。
参考:詳しくは、以下の書籍を参照してください(練習問題もあります)。
Visual Studio CodeでPlantUMLの拡張機能を追加する
Visual Studio CodeでPlantUMLを使えるようにするには以下の手順で設定します。
次の参考サイトの手順に従って準備します。
Visual Studio Codeの設定を変更する
- 「ファイル」メニュー → ユーザー設定 → 設定 を選択する。
- メニューから「よく使用するもの」を選択します。
- 「Files:AutoSave」:「afterDelay」を選択する。これを選択すると自動保存されるようになります。
- 「Editor:Font Size」:フォントサイズを14に設定します。
- 「Editor:Font Family」:プログラミング用フォントの「Ricty Diminished」を選択します。
- 「Editor:Tab Size」:Tabキーを押したときに空白を何文字入れるかを設定します。今回は「4」を設定しています。
- 「Editor:Render Whitespace」:半角空白文字を表示するかどうかを設定します。意図しない空白文字が入ることで不具合につながることを防止するため、「all」を選択します。
- 「Editor:Word Wrap」:行の折り返しを設定します。「on」を選択します。
- メニューから「テキストエディター」→「ファイル」を選択します。
- 「Files:Auto Save Delay」:上記で自動保存するよう設定した場合、何ミリ秒後に自動保存するかを設定できます。
- 「Files:Auto Save Delay」:上記で自動保存するよう設定した場合、何ミリ秒後に自動保存するかを設定できます。