2012-05-22 40 views
10

Tôi sẽ cố gắng giải thích tốt nhất của mình.Làm thế nào để sử dụng lớp chung với các đối tượng cụ thể trong một bối cảnh tĩnh?

Tôi sử dụng Play Framework 2 và tôi sẽ thực hiện rất nhiều hành động CRUD. Một số người trong số họ sẽ được nhận dạng, vì vậy tôi muốn KISS và DRY vì vậy lúc đầu tôi đã suy nghĩ về một lớp trừu tượng có chứa các phương pháp list, details, create, updatedelete, với đối tượng chung và mở rộng lớp này bằng cách xác định đối tượng sử dụng (Model & Form):

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 
    } 
} 

Và một lớp học mà sẽ sử dụng CRUD:

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 
    } 
} 

này sẽ làm việc nếu tôi không phải là trong một bối cảnh tĩnh.

Nhưng vì vậy, tôi có thể làm gì?

+0

Tại sao không chỉ đơn giản là chuyển sang phương pháp ví dụ? Thừa kế không hoạt động trên các phương thức lớp trong Java. – Vlad

+0

Một ý tưởng khác có thể là thay thế thừa kế bằng bố cục: chỉ có các cá thể của CrudController và ủy nhiệm các hoạt động cho đối tượng chứa đối tượng cụ thể. (Tất cả điều này phụ thuộc vào thiết kế của bạn, tất nhiên.) – Vlad

+0

@Vlad: Đối với câu hỏi đầu tiên, tôi không thể, Play yêu cầu phương pháp tĩnh cho bộ điều khiển. Bây giờ cho lần thứ hai, tôi không chắc chắn để hiểu, bạn có thể xây dựng (hoặc tạo ra một câu trả lời mới)? –

Trả lời

13

này có thể đạt được bằng đoàn: định nghĩa một lớp Java thông thường chứa logic hành động CRUD:

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 
} 

Sau đó, bạn có thể định nghĩa một bộ điều khiển chơi có một lĩnh vực tĩnh chứa một thể hiện của Crud<City>:

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

Và bạn đã gần hoàn thành: bạn chỉ cần cần phải xác định các tuyến đường cho những hành động CRUD:

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

Lưu ý: ví dụ này tạo ra phản ứng JSON cho brevety nhưng nó có thể làm cho các mẫu HTML. Tuy nhiên, vì các mẫu Play 2 được nhập tĩnh nên bạn cần phải chuyển tất cả chúng dưới dạng tham số của lớp Crud.

+0

Imo trả lại một cái nhìn tùy thuộc vào bộ điều khiển là phần khó khăn, làm thế nào bạn sẽ giải quyết được điều đó? –

+0

Đó thực sự là một vấn đề thú vị. Câu hỏi này đã được nhiều hơn về cách sử dụng lại một số logic mặc dù bản chất tĩnh của bộ điều khiển (mà không cho phép thừa kế). Có lẽ bạn nên mở một câu hỏi khác? –

+1

Đúng, nó không thực sự nằm trong phạm vi của câu hỏi này. Nhưng chỉ là tự hỏi khi đọc câu trả lời của bạn, mà tôi thích! Có lẽ tôi sẽ mở một câu hỏi khác tối nay. –

4

:

Ý tưởng sau đây có thể giúp (Disclaimer Tôi không có kinh nghiệm với play framework.):

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(); 
    } 

} 

Bằng cách này bạn có thể tạo ra một hệ thống các hiện thực.

(Điều này phải có một số mẫu thiết kế lạ mắt, được đặt tên, nhưng tôi không biết tên ATM.)

+0

Có một số ý tưởng hay đằng sau câu trả lời của bạn, nhưng những gì tôi đang tìm kiếm, là có một lớp theo Mô hình để sửa đổi trong cơ sở dữ liệu (thành phố, v.v.). Bởi vì khi tôi xác định các tuyến đường, tôi cần phải trỏ chúng đến một lớp cụ thể (bộ điều khiển). Bộ điều khiển này sẽ xác định mô hình để sử dụng. Vì vậy, nó không phải là một vấn đề nếu CrudController thay đổi, tôi chỉ cần viết càng ít mã càng tốt cho mỗi bộ điều khiển Crud cho trường hợp mã giống hệt nhau giữa các lớp khác nhau. –

+0

@ cx42net: Tôi không hiểu phần "có một lớp theo Mô hình". Điều này có nghĩa là đối với mỗi 'Mô hình' có thể có một lớp bắt nguồn từ' CrudController' (hoặc có lẽ là một thể hiện của 'CrudController')? – Vlad

+0

Ồ, điều này sẽ không hoạt động, vì không có trường hợp nào. Chờ đã, tôi sẽ cập nhật nó. – Vlad

Các vấn đề liên quan