Классическая реализация Singleton в OCaml - PullRequest
1 голос
/ 11 февраля 2009

Я пытаюсь концептуализировать шаблон проектирования Singleton (qua Java) в OCaml и видел когда-либо экземпляр, ссылающийся на функторы или модули, ни один из которых я не использую в качестве доказательства концепции работы GoF. В основном, я хотел бы воссоздать следующую функциональность, используя OCaml:

public class Singleton
{
 private static Singleton UniqueInstance; 
 private Singleton(){}
 public static Singleton getInstance()
 {
  if(UniqueInstance==null)UniqueInstance=new Singleton();
  return UniqueInstance;
 }
}

Возможно ли это без модулей или функторов?

Ответы [ 2 ]

4 голосов
/ 12 февраля 2009

Можете ли вы объяснить , почему модульное решение не работает для вас? Модули действительно являются естественным способом сделать то, что вы сделали бы с синглтоном на других языках.

Как правило, шаблоны в стиле GOF в OCaml в значительной степени не имеют значения. Действительно, объекты в OCaml в значительной степени не имеют значения. Люди из ОО часто думают, что им следует начать с использования ОО-функций в OCaml, но это ошибка. Большинство проблем, которые решаются с объектами на других языках, решаются с помощью параметрического полиморфизма, алгебраических типов данных и модулей в OCaml. Функторы - это немного более сложная тема, и объекты находятся там далеко. Вы не должны касаться объектной системы, пока не станете опытным пользователем остального языка.

3 голосов
/ 11 февраля 2009

Объекты в Ocaml не могут иметь статические / глобальные методы. Вы можете попробовать Ближайшие объекты . Предостережение, я думаю, что вы все еще можете сделать obj.copy, чтобы получить копию объекта, и каждый раз, когда они оцениваются, они возвращают новый объект (так что вы не можете передать параметры объекту, ну, вы можете, с некоторой инкапсуляцией и глобальным логическое, но теперь вы имеете дело с модулями). Конечно, если у вас есть что-то вроде этого примера,

let p = object 
   val mutable x = 0
   method get_x = x
   method move d = x <- x + d
end

p будет оцениваться один раз, и вы будете получать к нему доступ каждый раз. Конечно, p # copy может испортить вам жизнь. Модули - это путь сюда. OO-функции Ocaml не такие «мощные», как другие языки. Это, конечно, не цель проекта, это модульная система , очень мощная .

Модули являются (глобальными) синглетонами. Там действительно нет ничего, что вы должны написать, чтобы построить их. Они неявно в языке. Например, как насчет входа в файл:

---logging.ml
(* default channel to log *)
let log_channel = ref stdout

(* set the log to a channel *)
let set_log_chan chan = log_channel := chan

(* timestamp of log -- kinda heavy weight, but just for kicks *)
let get_log_prequel () = 
    let time = Unix.localtime (Unix.time ()) in
    (* format the time data into "y/m/d - h:m:s" format *)
    Printf.sprintf  "%d/%02d/%02d - %02d:%02d:%02d"
                    (time.Unix.tm_year+1900) time.Unix.tm_mon time.Unix.tm_mday
                    time.Unix.tm_hour time.Unix.tm_min time.Unix.tm_sec

(* log a string to the channel *)
let log_string str =
    output_string (!log_channel) ((get_log_prequel ())^":\t"^str^"\n")

---logging.mli
set_log_chan : in_channel -> unit
log_string : string -> unit

Я думаю, вы поняли это здесь. Синглтон неявный, верно? На самом деле не существует экземпляров, как в объектах, но это то, что вы хотите в одиночном. Вы просто начинаете использовать его в других файлах, таких как Logging.log_string "parsed file "^file_name^" successfully." и так далее, где угодно и всегда используете один и тот же канал.

С помощью функторов вы можете составлять свои модули для добавления разнообразия. Как указание модуля / функции для генерации приквела для вывода, и так далее.

...