2012-05-22 20 views
10

Elimden geleni açıklamaya çalışacağım.Statik bir bağlamda belirli nesnelere genel sınıf nasıl kullanılır?

Play Framework 2'yi kullanıyorum ve çok fazla CRUD işlemi yapacağım. Bazıları identitcal olacak, bu yüzden KISS ve DRY istiyorum, bu yüzden genel bir nesne olan list, details, create, update ve delete yöntemlerini içeren soyut bir sınıf hakkında düşünüyordum ve bu sınıfı Ben statik bir şekilde olmasaydı

public class Cities extends CrudController { 
    protected static Model.Finder<Long, City> finder = City.find; 
    protected static Form<City> form = form(City.class); 

    // I can override a method in order to change it's behavior : 
    public static Result list() { 
     // some different code here, like adding some where condition 
    } 
} 

Bu çalışacak:

public abstract class CrudController extends Controller { 
    protected static Model.Finder<Long, Model> finder = null; 
    protected static Form<Model> form = null; 

    public static Result list() { 
     // some code here 
    } 

    public static Result details(Long id) { 
     // some code here 
    } 

    public static Result create() { 
     // some code here 
    } 

    public static Result update(Long id) { 
     // some code here 
    } 

    public static Result delete(Long id) { 
     // some code here 
    } 
} 

Ve CRUD kullanacağı bir sınıfı: nesne (Model & Formu) kullanmak için.

Fakat durum böyleyken nasıl yapabilirim?

+0

Neden basitçe örnek yöntemlerine geçmiyorsunuz? Kalıtım Java'daki sınıf yöntemleri üzerinde çalışmaz. – Vlad

+0

Başka bir fikir de mirasın kompozisyonla değiştirilmesi olabilir: sadece CrudController örneklerine sahip olmak ve işlemleri özel olarak içerilen nesneye devretmek olabilir. (Bu, elbette tasarımınıza bağlıdır.) – Vlad

+0

@Vlad: İlk soru için, yapamıyorum, Denetleyici için statik yöntem gerektirir. Şimdi ikincisi için anlayamıyorum, detaylandırır mısınız (veya yeni bir cevap oluşturabilir)? –

cevap

13

Bu yetkisinin kullanılmasına elde edilebilir: REZİL eylemleri mantığını içeren normal bir Java sınıfı tanımlamak:

public class Crud<T extends Model> { 

    private final Model.Finder<Long, T> find; 
    private final Form<T> form; 

    public Crud(Model.Finder<Long, T> find, Form<T> form) { 
     this.find = find; 
     this.form = form; 
    } 

    public Result list() { 
     return ok(Json.toJson(find.all())); 
    } 

    public Result create() { 
     Form<T> createForm = form.bindFromRequest(); 
     if (createForm.hasErrors()) { 
      return badRequest(); 
     } else { 
      createForm.get().save(); 
      return ok(); 
     } 
    } 

    public Result read(Long id) { 
     T t = find.byId(id); 
     if (t == null) { 
      return notFound(); 
     } 
     return ok(Json.toJson(t)); 
    } 

    // … same for update and delete 
} 

Sonra Crud<City> bir örneğini içeren bir statik bakış alanına sahip bir Çalma denetleyicisi tanımlayabilirsiniz:

public class Cities extends Controller { 
    public final static Crud<City> crud = new Crud<City>(City.find, form(City.class)); 
} 

Ve neredeyse bitti: size sadece Crud eylemler için yön tanımlamak gerekir:

GET /     controllers.Cities.crud.list() 
POST /     controllers.Cities.crud.create() 
GET  /:id     controllers.Cities.crud.read(id: Long) 

Not: Bu örnek, brevety ilişkin JSON yanıtları üretir ancak HTML şablonları işlemek mümkündür. Ancak, Play 2 şablonları statik olarak yazıldığından, bunların tümünü Crud sınıfının parametreleri olarak geçirmeniz gerekir.

+0

Denetleyiciye bağlı olarak görünümü döndürmek zor bir kısımdır, bunu nasıl çözersiniz? –

+0

Bu gerçekten ilginç bir sorundur. Bu soru, kontrolörlerin statik yapısına (mirasa izin vermeyen) rağmen, bazı mantığın nasıl yeniden kullanılacağıyla ilgili daha fazlaydı. Belki başka bir soru açmalısın? –

+1

Doğru, bu sorunun kapsamı içinde değil. Ama sadece cevabını okurken merak ettim, hangisini sevdim! Belki bu gece başka bir soru açacağım. –

4

: Aşağıdaki fikri yardımcı olabilecek

(Feragat ı Play Framework ile hiçbir deneyimim var.):

public interface IOpImplementation { 
    public static Result list(); 
    public static Result details(Long id); 
    public static Result create(); 
    public static Result update(Long id); 
    public static Result delete(Long id); 
} 

public abstract class CrudController extends Controller { 
    protected static Model.Finder<Long, Model> finder = null; 
    protected static Form<Model> form = null; 

    protected static IOpImplementation impl; 

    public static Result list() { 
     return impl.list(); 
    } 

    public static Result details(Long id) { 
     return impl.details(id); 
    } 
    // other operations defined the same way 
} 

public class Cities extends CrudController { 

    public static Cities() { 
     impl = new CitiesImpl(); 
    } 

} 

Bu şekilde uygulamaların bir hiyerarşi oluşturabilirsiniz.

(Bu, bazı fantezi adlı tasarım deseni olmalı, ama isim ATM bilmiyorum.)

+0

Cevabınızın arkasında güzel bir fikir var, ama aradığım şey veritabanında (şehirler, vs.) değişiklik yapmak için Model tarafından bir sınıfa sahip olmak. Çünkü rotaları tanımladığımda, onları belirli bir sınıfa (denetleyici) yönlendirmem gerekiyor. Bu kontrolör hangi modeli kullanacağını tanımlayacaktır. CrudController değiştiğinde sorun değil, sadece her bir Crud kontrolörü için kodun mümkün olduğunca küçük bir kod yazması gerekiyor, çünkü kod çeşitli sınıflar arasında aynıdır. –

+0

@ cx42net: "Modele göre bir sınıfa sahip olmanın" bölümünü anlamadım. Bu, her bir 'Model' için 'CrudController' (türetilen CrudController')' den türetilmiş bir sınıf olmalıdır? – Vlad

+0

Oh, bu, hiçbir örnek olmadığı için işe yaramaz. Bekle, onu güncelleyeceğim. – Vlad

İlgili konular